That makes sense. Thanks, Ken! On Wed, Dec 7, 2016 at 11:00 AM, Ken Thomases <k...@codeweavers.com> wrote:
> 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 > > -- Charles _______________________________________________ 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