Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I remove value that was previously registered via [NSUserDefaults registerDefaults:] call

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?

like image 638
macwasik Avatar asked Sep 09 '10 11:09

macwasik


2 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.

like image 137
EthanB Avatar answered Sep 18 '22 18:09

EthanB


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.

like image 33
JAL Avatar answered Sep 20 '22 18:09

JAL