I have bunch of preference values registered via [NSUserDefaults registerDefaults:]
call on application startup. I need to replace them at some stage with new ones but new values scope (keys set) is less than initial one. So after I call [NSUserDefaults registerDefaults:]
again I have new values with some old that weren't replaced. Is there a possibility to remove previously registered values?
-
If you're working on iOS, the docs(http://developer.apple.com/library/ios/#documentation/Cocoa/Reference/Foundation/Classes/NSUserDefaults_Class/Reference/Reference.html) mention that "The contents of the registration domain are not written to disk; you need to call this method each time your application starts. You can place a plist file in the application's Resources directory and call registerDefaults: with the contents that you read in from that file." So I assume that, if you leave them out, they are left empty. Do you have any idea why the old values are left in the defaults? – Nick Oct 14 '10 at 12:34
3 Answers
To completely replace the registered defaults, you will replace the NSRegistrationDomain
domain (which is volatile, by the way).
To remove individual registered defaults, you get the values in the NSRegistrationDomain
, remove the offending key(s), and replace the domain.
A category on NSUserDefaults
might look something like this:
@implementation NSUserDefaults (UnRegisterDefaults)
- (void)unregisterDefaultForKey:(NSString *)defaultName {
NSDictionary *registeredDefaults = [[NSUserDefaults standardUserDefaults] volatileDomainForName:NSRegistrationDomain];
if ([registeredDefaults objectForKey:defaultName] != nil) {
NSMutableDictionary *mutableCopy = [NSMutableDictionary dictionaryWithDictionary:registeredDefaults];
[mutableCopy removeObjectForKey:defaultName];
[self replaceRegisteredDefaults:[mutableCopy copy]];
}
}
- (void)replaceRegisteredDefaults:(NSDictionary *)dictionary {
[[NSUserDefaults standardUserDefaults] setVolatileDomain:dictionary forName:NSRegistrationDomain];
}
@end
Motivation:
The reason I need this is because I want to turn on user-agent spoofing (for reasons of 3rd-party compatibility). User-agent spoofing only appears to work when the value is set via registerDefaults:
, so set...:forKey:
won't stop the user-agent string it. If I want to stop spoofing the user-agent some time later (without restarting the app), I need a way to remove defaults. Further, I don't want to clear the other registered defaults my app users. The above solution appears to accomplish this perfectly.
Swift 3 port of EthanB's original answer:
extension UserDefaults {
/// Unregisters a value set in the UserDefaults.registrationDomain, if it exists
func unregister(defaultsFor key: String) {
var registeredDefaults = volatileDomain(forName: UserDefaults.registrationDomain)
registeredDefaults[key] = nil
setVolatileDomain(registeredDefaults, forName: UserDefaults.registrationDomain)
}
}
Used in deinit
of my UIWebView
to restore the default user agent back to my app.

- 41,701
- 23
- 172
- 300
You can use removeVolatileDomainForName:
to remove the NSRegistrationDomain
. This clears all values registered via registerDefaults:
. But if you need to do this you’re most likely doing something wrong. The right way would be to actually store the new settings using one of the set...:forKey:
methods.

- 22,475
- 4
- 52
- 71
-
This solution won't fix my issue due to removeVolatileDomainForName works in level+1 stage than defaults – macwasik Sep 11 '10 at 21:54