0

I want to download modified Info.plist file into the Documents folder in the runtime and make iOS to read some value from it.(Something like swizzling) I know it's impossible to write on the main Info.plist file in the App bundle but I want to set some value like: "Privacy - Location When In Use Usage Description" or "UIApplicationShortcutItemTitle" I've seen some apps have done this. I was wondering how can I implement it.

I've done some work to replace the object:

class IconInfoBundle: Bundle {
    override var infoDictionary: [String : Any]? {
        let bundle: Bundle? = objc_getAssociatedObject(self, &iconInfoBundleKey) as? Bundle
        var propertyListFormat =  PropertyListSerialization.PropertyListFormat.xml //Format of the Property List.
        let plistPath: String? = bundle!.path(forResource: "Info", ofType: "plist")! //the path of the data
        let plistXML = FileManager.default.contents(atPath: plistPath!)!
        let plistDictonatry = try! PropertyListSerialization.propertyList(from: plistXML, options: .mutableContainersAndLeaves, format: &propertyListFormat) as? [String:Any]
        return plistDictonatry
    }

}

extension Bundle {

    class func setIconFromInfoPlist() {

        // TODO: - Dispatch once
        object_setClass(Bundle.main, IconInfoBundle.self)

        let bundleDisplaced = Bundle.displace
        objc_setAssociatedObject(Bundle.main,&iconInfoBundleKey, bundleDisplaced,.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
    }
}

and what is Bundle.displace?

extension Bundle {
    static var name: String {
        return Bundle.main.object(forInfoDictionaryKey: "CFBundleName") as! String
    }


    static var displace: Bundle {


        guard let documentsDirectory = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first else {
            fatalError("Couldn't find Documents path")
        }

        let path = documentsDirectory.appending("/\(Bundle.name).bundle")

        guard FileManager.default.fileExists(atPath: path) else {
            fatalError("There is no file in this PATH:\(path)")
        }

        guard let bundle =  Bundle(path: path) else {
            fatalError("the file is not like a Bundle")
        }

        return bundle
    }
}

I've called Bundle.setIconFromInfoPlist() in the main.swift (the very first place I can run my code) but the problem is the Location access message is not changing to what I set in Info.plist (located in the Documents folder)

Look at this property in one app from App Store:

Contact Permission Message in the info.plist from App main bundle

Contact Permission Message in English from the info.plist from Secondary bundle downloaded later in Documents

Emran
  • 79
  • 1
  • 11
  • 2
    Not possible, because apple checks everything in review time and you cant override privacy options on runtime. – Mojtaba Hosseini Sep 17 '19 at 11:27
  • Check my answer [here](https://stackoverflow.com/a/57583433/7551807), I explained on how to make a custom .plist file – Mussa Charles Sep 17 '19 at 11:43
  • 1
    permission dialogs, such as the location permission dialog are presented *out of process*; they are presented by an iOS component, not your own code. This prevents that any modification of the process by your app. – Paulw11 Sep 17 '19 at 12:15
  • It's possible! you can download an info.plist file and let os read some data from it rather than main info.plist. I've seen it by myself in an app! @MojtabaHosseini – Emran Sep 17 '19 at 13:50
  • I assume you haven't read my entire question. Thanks anyway @MussaCharles – Emran Sep 17 '19 at 13:51
  • some data, not all of them. And privacy is not included. Perhaps pointing to that app or present screenshots of that app you are talking about with different messages could help. – Mojtaba Hosseini Sep 17 '19 at 13:58
  • You say "Location access message is not changing". If you set a custom key/value in the Info.plist file, does that change for you? – Derek Sep 17 '19 at 14:04
  • @Paulw11 You are right, I was thinking so but it seems you can swizzle some system api which is called when request for "Location Permission Message". I've added some image to my post which shows it's possible! – Emran Sep 18 '19 at 06:39
  • @MojtabaHosseini Yep, You are right. I can not do such a thing whit "Icon Files" api which you can set the app icon cause the os reading it before app even opens. I've added some image to my post from the App which I've talked about. Two version of Info.plist. – Emran Sep 18 '19 at 06:43
  • @Derek Yes. If I set it in the main Info.plist in my main app bundle it will change. But I don't want to do so. I want to set in secondary Info.plist which I've downloaded it in the Documents and make OS read message from that file. – Emran Sep 18 '19 at 06:45
  • You **can** change the icon. But there is no need to change the info.plist for that. I asked for screenshots of that app you mentioned. So I can see what part of info.plist is changing there. – Mojtaba Hosseini Sep 18 '19 at 06:46
  • You can not change those detail which includes Privacy options but as you said that some of the apps doing that Can you share app name which is doing same as you said in your question ? – CodeChanger Sep 18 '19 at 07:02
  • @CodeChanger I'm afraid not. The app is removed from App Store yesterday and is not accessible now. – Emran Sep 18 '19 at 07:22
  • 2
    Even if you could figure out how to do this, it almost certainly violates [Guideline 2.5.2](https://developer.apple.com/app-store/review/guidelines/#software-requirements) – Paulw11 Sep 18 '19 at 08:12
  • @MojtabaHosseini Dear Mojtaba I can not send screenshots and mention the app name because of possible consequences. I wanted to share both Info.plist files so you can see it but apparently I can't share files here. I know that I can change the icon with an Alternative Icon api (or normal Assets folder) but I don't want to ship the icons with my app. I want to download it later and replace the previous version but I realize I couldn't do such a thing. – Emran Sep 19 '19 at 19:28

0 Answers0