2

I have set up a preference using multi_preference in my Root.plist in my Settings.bundle 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>StringsTable</key>
    <string>Root</string>
    <key>PreferenceSpecifiers</key>
    <array>
        <dict>
            <key>Type</key>
            <string>PSMultiValueSpecifier</string>
            <key>Key</key>
            <string>multi_preference</string>
            <key>DefaultValue</key>
            <string>Show First Page</string>
            <key>Title</key>
            <string>My Option</string>
            <key>Identifier</key>
            <string>myOption</string>
            <key>Titles</key>
            <array>
                <string>Option 1</string>
                <string>Option 2</string>
            </array>
            <key>Values</key>
            <array>
                <string>Option 1</string>
                <string>Option 2</string>
            </array>
        </dict>
    </array>
</dict>
</plist>

When I try to get the value from the list using the following code:

NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *option = [defaults arrayForKey:@"myOption"];

I always get nil returned.

I am using the simulator and I have set initial values in my applications settings.

Anybody got any ideas what I have missed out?

Thanks

iphaaw

iphaaw
  • 6,764
  • 11
  • 58
  • 83

2 Answers2

4

Sorry for my previous answer, I misunderstood the question. Let's try this again.

Looking at the documentation for PSMultiValueSpecifier, the key for NSUserPreferences is stored in the "Key" key in the plist, not the "Identifier" key. So in this case, [defaults arrayForKey:@"multi_preference"] should get you your value. Or you could change it like this and it should work with "myOption":

    <dict>
        <key>Type</key>
        <string>PSMultiValueSpecifier</string>
        <key>Key</key>
        <string>myOption</string>
        <key>DefaultValue</key>
        <string>Option 1<string>
        <key>Title</key>
        <string>My Option</string>
        <key>Titles</key>
        <array>
            <string>Text for Option 1</string>
            <string>Text for Option 2</string>
        </array>
        <key>Values</key>
        <array>
            <string>Option 1</string>
            <string>Option 2</string>
        </array>
    </dict>
Anomie
  • 92,546
  • 13
  • 126
  • 145
  • NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; NSString *mypref = [defaults arrayForKey:@"multi_preference"]; mypref returns nil. If I write the defaults on startup with the following code it seems to work: NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; NSDictionary *appDefaults = [NSDictionary dictionaryWithObject:@"Option 1" forKey:@"multi_preference"]; [defaults registerDefaults:appDefaults]; [defaults synchronize]; but this overwrites my prefs. – iphaaw Mar 05 '11 at 20:46
  • Does it work if you open the Settings application for your app before opening your application? If so, you simply need to use the `registerDefaults:` method on NSUserDefaults to specify the default values. See [this question](http://stackoverflow.com/questions/510216/can-you-make-the-settings-in-settings-bundle-default-even-if-you-dont-open-the-s) for help in loading the dictionary for `registerDefaults` from the settings bundle. – Anomie Mar 05 '11 at 21:00
  • Thanks for your assistance. I don't know what happened. It seems that just renaming my key fixed my problem. – iphaaw Mar 06 '11 at 22:09
  • Very old question, so I'll simply add a comment. You're asking for an array but you should be asking for a string. The default type and each element of the array is a string. The array is used only to present the strings to the user. Retrieving the value returns a string. – Victor Engel Sep 21 '20 at 02:49
1

Please check the question

The problem is the selected value is nil before user interacted with app settings.

The solution for this would be registering default values from Root.plist to UserDefaults when app launches.

I have updated the code of the original question to Swift 5:

static func registerSettingsDefaults()
{
    // Get Settings bundle path
    guard let settingsBundle = Bundle.main.path(forResource: "Settings", ofType: "bundle") else {
        assertionFailure("Could not find Settings bundle")
        return
    }

    // Get settings plist
    let settings = NSDictionary(contentsOfFile: settingsBundle + "/Root.plist")

    // Get preferences dictionary
    guard let preferences = settings?.object(forKey: "PreferenceSpecifiers") as? [[String: Any]] else {
        assertionFailure("Could not find preferences")
        return
    }

    // Filter out default values from Settings
    var defaultsToRegister: [String: Any] = [:]
    preferences.forEach { dictionary in
        if let key = dictionary["Key"] as? String {
            defaultsToRegister[key] = dictionary["DefaultValue"] as? String
        }
    }

    UserDefaults.standard.register(defaults: defaultsToRegister)
}

And I call it in didFinishLaunchingWithOptions:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool
{
    // Register Settings defaults
    registerSettingsDefaults()
serhii.syrotynin
  • 241
  • 1
  • 14