Re: Elementary NSUserDefaults Question
Re: Elementary NSUserDefaults Question
- Subject: Re: Elementary NSUserDefaults Question
- From: Ken Thomases <email@hidden>
- Date: Wed, 07 Dec 2016 10:00:09 -0600
On Dec 7, 2016, at 9:25 AM, Charles Jenkins <email@hidden> wrote:
>
> I may be misusing NSUserDefaults. I want to store the name of a background
> music file, which may be nil if the user doesn’t want to hear anything. For
> the time being, I have only two settings for my variable
> “currentBackgroundMusicFileName”: either a file that I distribute with the
> app, or nil.
>
> When the app starts up, we call NSUserDefaults.standard.register( [ “bgm” :
> <myfilename> ) to default to the real file name, so the user will hear
> music on first run. Then I call NSUserDefaults.standard.object( forKey:
> “bgm” ) as? String to read the current setting.
>
> When I run the app, I go into my settings and select “None” as the
> background music file I want to hear, and the variable gets changed and we
> call NSUserDefaults.standard.set( nil, forKey: “bgm” ). The music is
> silenced.
>
> But when I kill the app and start again, the music comes back. Is it it a
> mistake to try using nil as an object value? Perhaps object( forKey: ) is
> meant to return the registered default value again instead of the nil when
> I reload the app, making it impossible for me to use nil as a valid value?
Sort of.
The user defaults system organizes the defaults into a stack of "domains". For any given key, it consults the domains in order. If one domain doesn't have a value for the key, it continues on to the next domain. Like with a dictionary, nil is not a value, it's the absence of a value.
For purposes of this discussion, there are two relevant domains, the application domain and the registration domain, consulted in that order. The registration domain is the combination of whatever was passed to the register() method. It is a volatile domain that's not persisted. It's recreated from scratch for each run of the app by your calls to register().
The app domain is where settings are saved for your app. It's a persistent domain. The various set(_:forKey:) methods modify this domain. Most of them add or modify a value for the key, but set(nil, forKey:"someKey") is a special case and removes the key-value pair for the given key.
So, your attempt to set nil for a key only ever removes it from the app domain (where it never was in the first place), leaving the user defaults system to proceed to the next domain, the registration domain, to satisfy any future lookups.
You should instead use a boolean key to control whether background music plays. If you really intend to allow the user to change which file to play from, you could continue to have a key for the file name, but it would be subordinate to the boolean as to whether anything should play at all.
Regards,
Ken
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden