Settings bundle values returning nil
Default values can be taken from Settings.bundle
and added to UserDefaults. Following function can be called in AppDelegate.swift
from didFinishLaunchingWithOptions
.
func setDefaultsFromSettingsBundle() {
//Read PreferenceSpecifiers from Root.plist in Settings.Bundle
if let settingsURL = Bundle.main.url(forResource: "Root", withExtension: "plist", subdirectory: "Settings.bundle"),
let settingsPlist = NSDictionary(contentsOf: settingsURL),
let preferences = settingsPlist["PreferenceSpecifiers"] as? [NSDictionary] {
for prefSpecification in preferences {
if let key = prefSpecification["Key"] as? String, let value = prefSpecification["DefaultValue"] {
//If key doesn't exists in userDefaults then register it, else keep original value
if UserDefaults.standard.value(forKey: key) == nil {
UserDefaults.standard.set(value, forKey: key)
NSLog("registerDefaultsFromSettingsBundle: Set following to UserDefaults - (key: \(key), value: \(value), type: \(type(of: value)))")
}
}
}
} else {
NSLog("registerDefaultsFromSettingsBundle: Could not find Settings.bundle")
}
}
Apparently the cause is that if my settings in the plist
have defaults defined and the user has not explicitly set a value, then the value displayed in the Settings app will be the defaults from the plist
file, however the NSUserDefaults
API will still return nil
.
Unfortunately this means that if the default value is meaningful (such as a default web-service address URI: "http://www.example.com
") it must exist twice in my project: as a default in the plist
and in my program code:
Root.plist:
<dict>
<key>Key</key> <string>mySettingKey</string>
<key>Title</key> <string>Some address</string>
<key>Type</key> <string>PSTextFieldSpecifier</string>
<key>DefaultValue</key> <string>http://www.example.com</string>
<key>IsSecure</key> <false />
<key>KeyboardType</key> <string>Alphabet</string>
</dict>
Program.swift:
let ud = NSUserDefaults.standardUserDefaults()
ud.synchronize()
var mySettingValue = ud.stringForKey("mySettingKey")
if mySettingValue == nil {
mySettingValue = "http://www.example.com"
}
That's surprising.