On Dec 7, 2016, at 9:25 AM, Charles Jenkins <cejw...@gmail.com> 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 (Cocoa-dev@lists.apple.com)

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:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Reply via email to