iOS 中 NSUserDefaults 的默认值初始化问题
iOS 中的 SettingsBundle 可以很方便的实现应用设置界面,你甚至都不用像 Android 中一样去自己写 PreferenceActivity
;然后通过 NSNSUserDefaults
就可以像 Android 中的 SharedPreferences
一样存取信息。
而且,与 Android 只能在读取时设置默认值不同;对于 iOS ,你可以在创建 SettingsBundle 时就预先给每个选项设置默认值。
但是最近在 SettingsBundle 实际使用中发现一个问题:
虽然设置了默认值,但代码中通过 NSUserDefaults
读到的始终为空,必须进入设置页面点一下才会读取到。
自己初步分析,应该是默认值没有被初始化。
StackOverflow 上果然也有人遇到了类似的问题。
解决方式是:先从 plist 文件将所有 DefaultValue
读取到一个 NSMutableArray
,然后调用 NSUserDefaults
的 registerDefaults:
方法初始化。
这里自己也写了一个初始化方法:
-(void)checkUserDefaultsForKey:(NSString*)prefKey
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if (![defaults objectForKey:prefKey])
{
// Read plist file's path from MainBundle:
NSString *mainBundlePath = [[NSBundle mainBundle] bundlePath];
NSString *plistPath = [mainBundlePath stringByAppendingPathComponent:@"Settings.bundle/Root.plist"];
// Read dictionary from plist file:
NSDictionary *plistDic = [NSDictionary dictionaryWithContentsOfFile:plistPath];
// Read Preferences array from dictionary:
NSMutableArray *prefArray = [plistDic objectForKey:@"PreferenceSpecifiers"];
NSMutableDictionary *defaultsDic = [NSMutableDictionary dictionary];
// Travel all properties:
for(int i = 0; i < [prefArray count]; i++)
{
NSString *key = [[prefArray objectAtIndex:i] objectForKey:@"Key"];
if(key)
{
// Write property's DefaultValue to dic:
id value = [[prefArray objectAtIndex:i] objectForKey:@"DefaultValue"];
[defaultsDic setObject:value forKey:key];
}
}
// Save DefaultValues:
[defaults registerDefaults:defaultsDic];
[defaults synchronize];
}
}
上面注释还算详尽,就不细说了。
然后,我们在读取 NSUserDefaults
中的值时,如果有设置过默认值,只需要通过其中的一个调用上面的方法就可以了:
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[self checkUserDefaultsForKey:@"pref_name"];
NSLog(@"Name: %@", [defaults stringForKey:@"pref_name"]);
// There's no need to check again.
NSLog(@"Level: %d", [defaults integerForKey:@"pref_level"]);
因为上面的 checkUserDefaultsForKey:
方法会遍历所有 DefaultValue
,所以不用再次检验和初始化。