My apps use [NSUserDefaults standardUserDefaults] as a quick and dirty database to store state about the user and the app itself. The trouble with NSUserDefaults is that its flexibility allows for a big mess down the line, for example when different files all set and read different keys in the dictionary in their own way. You don't get to enforce rules, you can screw up the key name etc..
I wrote a simple singleton "manager-style" wrapper for NSUserDefaults which both takes care of setting the default values when used, hides the name of keys used to fetch the values and encapsulates some extra logic, such as encoding to NSData, when storing and retrieving objects from the store.
At this point they're properties backed by a read/set accessor, but something is rubbing me wrong about it and I'm wondering if perhaps there's a more elegant way of achieving the same result. There's quite a bit of boilerplate and the syntax ends up being somewhat unpleasant. To give you an example:
.h:
@interface UserDefaultsManager: NSObject
+ (UserDefaultsManager *)sharedInstance;
@property (nonatomic, assign) NSInteger somethingImTracking;
@end
and .m:
NSString * const kSomethingImTracking= @"SomethingImTracking";
@implementation UserDefaultsManager
[...]
- (NSInteger)somethingImTracking
{
return [[[NSUserDefaults standardUserDefaults] objectForKey:kSomethingImTracking] intValue];
}
- (void)setSomethingImTracking:(NSInteger)somethingImTracking
{
[[NSUserDefaults standardUserDefaults] setInteger:somethingImTracking forKey:kSomethingImTracking];
}
and to access:
NSInteger foo = [UserDefaultsManager sharedInstance].somethingImTracking;
Personally I use string constants to store the key names, and just access the user defaults object directly, but I don't tend to use defaults to a huge extent, or in many different classes.
One improvement I'd make to your code is to have them all as class methods instead. There is no benefit to a singleton (you're not maintaining any state, that's all in the defaults object) and this takes a bit of the ugly repetitive code (...sharedInstance
) out of your use pattern.
synchronize
is not necessary to include every time you set. It is only needed when accessing defaults values from different threads in quick succession. The OS calls it itself periodically as well.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With