iPhone模拟器默认值中的不一致默认值(NSUserDefaults)行为

时间:2009-01-24 02:35:26

标签: iphone ios-simulator

在开发iPhone应用程序并尝试通过标准NSUserDefaults机制保存首选项时,我遇到了非常不一致的结果。我正在使用Erica Sadun的iPhone Developer's Cookbook中的代码(精彩的书btw),它看起来像这样:

(void) updateDefaults
{
    NSMutableArray *spells =  [[NSMutableArray alloc] init];
    NSMutableArray *locs = [[NSMutableArray alloc] init];

    for (DragView *dv in [boardView subviews]) 
    {
        [spells addObject:[dv whichSpell]];
        [locs addObject:NSStringFromCGRect([dv frame])]; 
    }

    [[NSUserDefaults standardUserDefaults] setObject:spells forKey:@"spells"];
    [[NSUserDefaults standardUserDefaults] setObject:locs forKey:@"locs"];
    [[NSUserDefaults standardUserDefaults] synchronize];

    [spells release];
    [locs release];
}

值有时会被保存,有时会被恢复。我无法确定它是什么有效或无法使它发挥作用。

还有其他人有类似的经历吗?关于什么可能使它工作的任何建议?同步方法是强制磁盘写入并使值保存的最佳方法,还是有更好的方法(包括生产和模拟器)。

由于 莱恩

2 个答案:

答案 0 :(得分:2)

您应该使用NSKeyedArchiver来保存数组,例如:

[[NSUserDefaults standardUserDefaults] setObject:[NSKeyedArchiver archivedDataWithRootObject:spells] forKey:@"spells"];
[[NSUserDefaults standardUserDefaults] setObject:[NSKeyedArchiver archivedDataWithRootObject:locs] forKey:@"locs"];
[[NSUserDefaults standardUserDefaults] synchronize];

如果它是自定义类,您还应该确保您的spells类实现NSCoding协议(encodeWithCoder:和initWithCoder :)。看起来你的locs是NSStrings,它会存档很好。

您还需要执行类似

的操作
NSData *dataRepresentingSavedSpells = [currentDefaults objectForKey:@"spells"];
if (dataRepresentingSavedSpells != nil)
{
    NSArray *oldSpells = [NSKeyedUnarchiver unarchiveObjectWithData:dataRepresentingSavedSpells];
}

从默认值中加载旧值。

我在退出时使用synchronize写入磁盘,根据我的经验,它非常可靠。

答案 1 :(得分:2)

在Mac OS X上,也可能在iPhone OS上,默认数据库只能包含属性列表对象:NSString,NSNumber,NSArray,NSDictionary和NSData。

从你的代码片段中不清楚咒语是什么类型,但如果它不是上述之一,它将不会存储在默认数据库中。您的选择是:

  1. 编写一个方法,将对象转换为plist表示形式。换句话说,一种从对象创建NSDictionary的方法和另一种使用NSDictionary初始化对象的方法。您也可以选择将其存储为NSArray或NSString。
  2. 使您的对象实现NSCoding协议,然后使用NSKeyedArchiver将对象转换为NSData对象,并使用NSKeyedUnarchiver将其转换回来。