I have bunch of preference values registered via [NSUserDefaults registerDefaults:]
call on application startup. I need to replace them at some stage with new o
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.
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.