14

我正在使用 KVC 序列化一个NSObject并尝试将其保存到NSUserDefaultsAttempt to insert non-property value当我尝试存储我的NSDictionary.

以下是相关对象的属性MyClass

@interface MyClass : NSObject
@property (copy,nonatomic) NSNumber* value1;
@property (copy,nonatomic) NSNumber* value2;
@property (copy,nonatomic) NSString* value3;
@property (copy,nonatomic) NSString* value4;
@property (copy,nonatomic) NSString* value5;
@property (copy,nonatomic) NSString* value6;
@property (copy,nonatomic) NSString* value7;
@property (copy,nonatomic) NSString* value8;
@end

当需要保存 MyClass 时,它会出现在此处:

-(void)saveMyClass
{
  NSArray* keys = [NSArray arrayWithObjects:
                @"value1",
                @"value2",
                @"value3",
                @"value4",
                @"value5",
                @"value6",
                @"value7",
                @"value8",
                nil];
  NSDictionary* dict = [self dictionaryWithValuesForKeys:keys];
  for( id key in [dict allKeys] )
  {
    NSLog(@"%@ %@",[key class],[[dict objectForKey:key] class]);
  }
  NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
  [defaults setObject:dict forKey:[NSString stringWithString:kMyClassKey]];
  [defaults synchronize];
}

产生这个输出:

2012-02-23 19:35:27.518 MyApp[10230:40b] __NSCFConstantString __NSCFNumber
2012-02-23 19:35:27.519 MyApp[10230:40b] __NSCFConstantString __NSCFNumber
2012-02-23 19:35:27.519 MyApp[10230:40b] __NSCFConstantString __NSCFString
2012-02-23 19:35:27.519 MyApp[10230:40b] __NSCFConstantString __NSCFString
2012-02-23 19:35:27.520 MyApp[10230:40b] __NSCFConstantString __NSCFString
2012-02-23 19:35:27.520 MyApp[10230:40b] __NSCFConstantString __NSCFString
2012-02-23 19:35:27.520 MyApp[10230:40b] __NSCFConstantString __NSCFString
2012-02-23 19:35:27.520 MyApp[10230:40b] __NSCFConstantString NSNull
2012-02-23 18:38:48.489 MyApp[9709:40b] *** -[NSUserDefaults setObject:forKey:]: Attempt to insert non-property value '{
    value1 = "http://www.google.com";
    value2 = "MyClassData";
    value3 = 8;
    value4 = "<null>";
    value5 = "http://www.google.com";
    value6 = 1;
    value7 = "http://www.google.com";
    value8 = 4SY8KcTSGeKuKs7s;
}' of class '__NSCFDictionary'.  Note that dictionaries and arrays in property lists must also contain only property values.`

如您所见, 中的所有对象dict都是属性列表值,其所有键都是NSString*. 为了执行此操作,我缺少什么琐事?还是我应该放弃并使用writeToFile或类似的?

4

3 回答 3

21

建议打印值的凯文的道具,当然其中一个NSNull是不是属性列表值的类型。谢谢!

我的问题的笨拙解决方案 - 迭代我刚刚生成的字典的键,dictionaryWithValuesForKeys并删除那些 type NSNull。叹

NSMutableDictionary* dict = [NSMutableDictionary dictionaryWithDictionary:[self dictionaryWithValuesForKeys:keys]];
for( id key in [dict allKeys] )
{
    if( [[dict valueForKey:key] isKindOfClass:[NSNull class]] )
    {
        // doesn't work - values that are entered will never be removed from NSUserDefaults
        //[dict removeObjectForKey:key];
        [dict setObject@"" forKey:key];
    }
}
于 2012-02-24T02:36:39.350 回答
21

在将字典保存到用户默认值时,我通常会归档和取消归档字典。这样您就不必手动检查NSNull值。

只需将以下两种方法添加到您的代码中。可能在一个类别中。

- (BOOL)archive:(NSDictionary *)dict withKey:(NSString *)key {
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    NSData *data = nil;
    if (dict) {
        data = [NSKeyedArchiver archivedDataWithRootObject:dict];
    }
    [defaults setObject:data forKey:key];
    return [defaults synchronize];
}

- (NSDictionary *)unarchiveForKey:(NSString *)key {
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    NSData *data = [defaults objectForKey:key];
    NSDictionary *userDict = nil;
    if (data) {
        userDict = [NSKeyedUnarchiver unarchiveObjectWithData:data];
    }
    return userDict;
}

然后你可以像这样归档任何字典(假设该方法在类中可用):

NSDictionary *dict = ...;
[self archive:dict withKey:@"a key of your choice"];

然后像这样再次检索它:

NSDictionary *dict = [self unarchiveForKey:@"a key of your choice"];
于 2013-06-25T10:11:51.537 回答
-2

如果需要存储;

  • 来自自定义对象的数据,
  • 或一组自定义对象

您可以使用 NSKeyedArchiver 方法。您可以查看 leviathan 对此方法的回答


但是,如果您尝试存储;

  • 包含 NSString 或 NSNumber 的字典(就像从 JSON 服务响应转换而来的字典),
  • 或这种字典的数组

你不需要使用 NSKeyedArchiver。您可以使用用户默认值。


就我而言,当我从用户默认值中检索字典时,它返回 nil,所以我认为 NSUserDefaults 不愿意保存我的字典。

但是,它被保存了,但是我使用了错误的 getter 方法从用户默认值中检索它;

[[NSUserDefaults standardUserDefaults] stringForKey:<my_key>]

请确保您使用了其中一个;

[[NSUserDefaults standardUserDefaults] dictionaryForKey:<my_key>]

或者;

[[NSUserDefaults standardUserDefaults] objectForKey:<my_key>]

在检查任何其他可能的原因之前。

于 2015-03-16T18:01:53.437 回答