Do you need help on a specific subject? Use the contact form (Request a blog entry) on the right hand side.

2015-03-27

Using the Info.plist

Every application on OS-X has a Info.plist file. When writing a utility like SwifterLog I find it nicer if the log levels can be set in a plist rather than in code.

But then it is necessary to access the Info.plist's properties during initialisation. Luckily Apple has made this easy. I use the following code to achieve this:

   init() {
        
        // Try to read the settings from the app's Info.plist
        
        if  let infoPlist = Bundle.main.infoDictionary,
            let config = infoPlist["SwifterLog"] as? Dictionary<String, AnyObject> {
            
                if let als = config["aslThreshold"] as? NSNumber {
                    if als.intValue >= Level.debug.rawValue &&
                       als.intValue <= Level.none.rawValue {
                        aslThreshold = Level(rawValue: als.intValue)!
                    } else {
                        // "Info.plist value for aslThreshold in SwifterLog out of bounds"
                    }

                }
                ....
        }

The corresponding entries in the plist file look as follows:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
...
<key>SwifterLog</key>
<dict>
<key>aslThreshold</key>
<integer>8</integer>
<key>logfileThreshold</key>
<integer>8</integer>
<key>stdoutThreshold</key>
<integer>0</integer>
<key>logfileMaxSizeInBytes</key>
<integer>1000000</integer>
<key>logfileMaxNumberOfFiles</key>
<integer>20</integer>
<key>logfileDirectoryPath</key>
<string></string>
</dict>
</dict>

</plist>

As you can see, I have added a dictionary item "SwifterLog" to the Info.plist file, and in that dictionary the configuration items for SwifterLog.

Consequently, in the source code I first need to gain access to the Info.plist, then the SwifterLog dictionary and then to the configuration items.
Swift allows us to encapsulate this nicely by using the conditional assignment. Notice that this also ensures that when the Info.plist does not contain a SwifterLog dictionary the default values in the code will be used. So the programmer has the choice of using the Info.plist, setting the configuration values in code, or simply using the default values.

Since errors are easily made, it is recommended to check the values in the Info.plist file before assigning them to the configuration parameters. This can save hours of bug-hunting!

Btw: Please note that I have manually changed the above code to be more compact for display purposes on screen. It is no longer identical to the swifterLog code. But you can check that out yourself by downloading SwifterLog...

Using the Info.plist is a nice enough feature, but when you code-sign your application it is no longer possible to change the Info.plist after distribution. While the end-user can edit the Info.plist file, GateKeeper won't start the application if the Info.plist is modified. If you need the capability for the end-user to modify plist values, you are out of luck. Unless you distribute the application without code-signing. I.e not through the App-store. Which of course can only be done for OS-X applications, not iOS applications.

Happy coding

Did this help?, then please help out a small independent.
If you decide that you want to make a small donation, you can do so by clicking this
link: a cup of coffee ($2) or use the popup on the right hand side for different amounts.
Payments will be processed by PayPal, receiver will be sales at balancingrock dot nl
Bitcoins will be gladly accepted at: 1GacSREBxPy1yskLMc9de2nofNv2SNdwqH

We don't get the world we wish for... we get the world we pay for.

No comments:

Post a Comment