与NSUserDefaults共舞

原文:http://www.dimzzy.com/blog/2011/02/dancing-with-nsuserdefaults/

在iOS app中,NSUserDefaults非常便利。程序员可以在其中存储应用程序选项,还可以通过iTunes备份它们——可以让它们在系统设置程序中显示。要实现这个,你需要创建一个Settings.bundle并描述清楚你想在设置程序中显示的选项以及如何显示它们。我们来演示一下如何添加一个Bool值bounces到设置程序中。首先创建Settings.bundle(通过Xcode的New FileàResourcesàSettingsBundle模板)。编辑Root.plist文件:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST1.0//EN"
    "http://www.apple.com/DTDs/PropertyList-1.0.dtd">

<plistversion="1.0">
<dict>
   
<key>StringsTable</key>
   
<string>Root</string>
   
<key>PreferenceSpecifiers</key>
   
<array>
       
<dict>
           
<key>Type</key>
           
<string>PSToggleSwitchSpecifier</string>
           
<key>Title</key>
           
<string>Bounces</string>
           
<key>Key</key>
           
<string>bounces</string>
           
<key>DefaultValue</key>
           
<true/>
       
</dict>
   
</array>
</dict>
</plist>

注意,我们把默认值设置为true。接下来,为Bounces属性创建helper类(用于存取该属性)。bounces属性是单例的,实现如下:

-(BOOL)bounces {
   
return[[NSUserDefaultsstandardUserDefaults] boolForKey:@"bounces"];
}

-(void)setBounces:(BOOL)bounces {
   
[[NSUserDefaultsstandardUserDefaults] setBool:bounces forKey:@"bounces"];
   
[[NSUserDefaultsstandardUserDefaults] synchronize];
}

 

这些东西你可能都知道,但这个代码里有两个Bug。

 

1. 如果存在默认值,你必需在Settings.bundle/Root.plist中加以说明同时需在代码中注册默认值。

 

也就是说,当你用NSUserDefaults读取属性时(至少是第一次),Root.plist中的默认设置是无效的。我不知道这种情况是否已documented,但我在测试中确实发现了这点。

要解决这个Bug,需要在你的Helpler类中加入下列方法:

+(void)initialize {
   
[[NSUserDefaultsstandardUserDefaults] registerDefaults:
       
[NSDictionarydictionaryWithObjectsAndKeys:
           
[NSNumber numberWithBool:YES],@"bounces",nil]];
}

译者注:

这段代码只在程序第一次运行时有效,如果第二次运行程序,则Defaults显示上次运行时修改过的值而不是默认值,如果你想再次看到默认值,只有把应用程序删除并重安装。其次,这段代码只能在设备上测试,在模拟器上看不到效果。


2.当应用程序进入后台,需要synchronize

发现这点时,我相当不解。当你的app转入后台,打开系统设置程序,改变属性值,然后切回app,你看不到新设置的属性值!要解决这个Bug,需要显式地调用synchronize方法:

-(void)applicationWillEnterForeground:(UIApplication*)application {
   
[[NSUserDefaultsstandardUserDefaults] synchronize];
   
// ...
}

这个问题并不会引起用户的注意,但一个高质量的应用程序应当注意这点。再次申明,本文内容不基于任何文档,仅仅是我在自己的测试中遇到的问题。

译者注:

实际上,苹果建议使用 NSUserDefaultsDidChangeNotifications通知来监听Preferences的改变。

注册观察者:

 NSNotificationCenter *center =[NSNotificationCenter defaultCenter];

[center addObserver:self

              selector:@selector(defaultsChanged:) 

                  name:NSUserDefaultsDidChangeNotification

                object:nil];

 

监听方法:

- (void)defaultsChanged:(NSNotification*)notification {

    // Get the user defaults

    NSUserDefaults *defaults = (NSUserDefaults*)[notification object];

 

    // Do something with it

    NSLog(@"%@", [defaultsobjectforKey:@"nameOfThingIAmInterestedIn"]);

}



你可能感兴趣的:(object,测试,xcode,application,resources,encoding)