Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can someone explain the search list feature in NSUserDefaults?

I am confused about the search list feature in NSUserDefaults. The class reference says about the standardUserDefaults class method that it sets up a standard search list consisting of five domains. The docs for that method also imply that this search list can be changed (boldness added by me):

Subsequent modifications to the standard search list remain in effect even when this method is invoked again—the search list is guaranteed to be standard only the first time this method is invoked.

Let's also look at the docs for init:

Return Value: An initialized NSUserDefaults object whose argument and registration domains are already set up.

Discussion: This method does not put anything in the search list.

In my understanding this is a contradiction: Either the search list is empty, or it contains entries for the argument and registration domains.

Anyway, I did a bit of experimentation:

NSUserDefaults* standardUserDefaults = [NSUserDefaults standardUserDefaults];
// We get nil, which is expected
NSLog(@"test 1: expecting nil, getting %@", [standardUserDefaults objectForKey:@"foo"]);
NSDictionary* registrationDomainDefaults = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:42] forKey:@"foo"];
[standardUserDefaults registerDefaults:registrationDomainDefaults];
// We get 42, which is expected
NSLog(@"test 2: expecting 42, getting %@", [standardUserDefaults objectForKey:@"foo"]);
[standardUserDefaults removeSuiteNamed:NSRegistrationDomain];
[standardUserDefaults removeVolatileDomainForName:NSRegistrationDomain];
// Here we get 42!
NSLog(@"test 3: expecting nil, getting %@", [standardUserDefaults objectForKey:@"foo"]);

NSUserDefaults* myUserDefaults = [[NSUserDefaults alloc] init];
// Here we also get 42!
NSLog(@"test 4: expecting nil, getting %@", [myUserDefaults objectForKey:@"foo"]);
[myUserDefaults removeSuiteNamed:NSRegistrationDomain];
[myUserDefaults removeVolatileDomainForName:NSRegistrationDomain];
// We still get 42 *sigh*
NSLog(@"test 5: expecting nil, getting %@", [myUserDefaults objectForKey:@"foo"]);

As you can see, I am trying to remove NSRegistrationDomain from the search list, by invoking both removeSuiteNamed: and removeVolatileDomainForName:. This does not work, at least not on iOS where I ran the tests, but I assume it's the same on Mac OS X. So these are my questions:

  1. On iOS, is there a way to remove one of the five standard domains from the search list of an NSUserDefaults object? Note that it does not necessarily have to be the object returned by standardUserDefaults, I would be happy to create my own object. In case it matters: I am particularly interested in getting rid of NSRegistrationDomain.
  2. If the answer to the above is "no", can we say that the five standard domains are simply "immutable" and that all the stuff in NSUserDefaults about adding/removing suites and persistent/volatile domains is about user-defined domains?
  3. Is there a way to find out what is in the search list of an NSUserDefaults object?

I suspect I already know the answers (no, yes, and no), but at least I am looking for someone with more experience to confirm my suspicions.

like image 319
herzbube Avatar asked Feb 05 '12 17:02

herzbube


People also ask

What types can you store natively in NSUserDefaults?

Storing Default Objects The NSUserDefaults class provides convenience methods for accessing common types such as floats, doubles, integers, Boolean values, and URLs. These methods are described in Setting Default Values.

Where are NSUserDefaults stored?

All the contents saved by NSUserDefaults is saved inside a plist file that can be found under Library -> Preferences -> $AppBundleId.

Is NSUserDefaults thread safe?

The NSUserDefaults class is thread-safe.

How do you check if NSUserDefaults is empty in Objective C?

There isn't a way to check whether an object within NSUserDefaults is empty or not. However, you can check whether a value for particular key is nil or not.


Video Answer


1 Answers

  1. To get rid of a domain like NSRegistrationDomain, you should use removeVolatileDomainForName:. However, this will not work with NSRegistrationDomain and NSArgumentDomain. These two cannot be removed. Try to register your own domain with setVolatileDomain:forName: instead. You'll be able to remove this one.

    I believe that in the five domains of the standardUserDefaults, you can remove your own domain with removePersistentDomainForName:, passing your bundle identifier. But I've not tried this out.

    Since NSGlobalDomain is persistent and you can only pass your own bundle identifier to removePersistentDomainForName:, I believe you can't remove NSGlobalDomain. Again, this is untested.

  2. I believe so, except for the persistent domain with your bundle identifier.

  3. No, but using -volatileDomainNames should be sufficient for most purposes.

like image 103
Thomas Deniau Avatar answered Oct 24 '22 03:10

Thomas Deniau