I'm using KVC to serialize an NSObject
and attempt to save it to NSUserDefaults
, which is giving me an Attempt to insert non-property value
when I try to store my NSDictionary
.
Following are the properties of the object in question, 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
When it is time to save MyClass it occurs here:
-(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];
}
which produces this output:
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.`
As you can see, all of the objects in the dict
are property list values and all of its keys are NSString*
. What trivia am I lacking in order to execute this? Or should I give up and use writeToFile
or similar?
In my case, when I retrieve the dictionary from user defaults it was returning nil, so I thought NSUserDefaults is unwilling to save my dictionary.
However, it was saved, but I was using the wrong getter method to retrieve it from user defaults;
Please make sure you used either;
or;
before checking any other possible reason.
Props to Kevin who suggested printing the values, of course one of which is of type
NSNull
which is not a property list value. Thanks!The kludgy solution to my problem - iterate over the keys of the dictionary I just produced so conveniently with
dictionaryWithValuesForKeys
and remove those of typeNSNull
. sighI usually archive and unarchive dictionaries when saving them to the user defaults. This way you don't have to manually check for
NSNull
values.Just add the following two methods to your code. Potentially in a category.
Then you can archive any dictionary like this (assuming the method are available in the class):
and retrieve it later on again like this: