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:
- On iOS, is there a way to remove one of the five standard domains from the search list of an
NSUserDefaultsobject? Note that it does not necessarily have to be the object returned bystandardUserDefaults, I would be happy to create my own object. In case it matters: I am particularly interested in getting rid ofNSRegistrationDomain. - 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
NSUserDefaultsabout adding/removing suites and persistent/volatile domains is about user-defined domains? - Is there a way to find out what is in the search list of an
NSUserDefaultsobject?
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.
To get rid of a domain like
NSRegistrationDomain, you should useremoveVolatileDomainForName:. However, this will not work withNSRegistrationDomainandNSArgumentDomain. These two cannot be removed. Try to register your own domain withsetVolatileDomain: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
NSGlobalDomainis persistent and you can only pass your own bundle identifier toremovePersistentDomainForName:, I believe you can’t removeNSGlobalDomain. Again, this is untested.I believe so, except for the persistent domain with your bundle identifier.
No, but using
-volatileDomainNamesshould be sufficient for most purposes.