How can I set another Info.plist instead of the main Info.plist file in the app main bundle(for some minor property)?

584 Views Asked by At

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

0

There are 0 best solutions below