3

I’m trying to save a NSMutableDictionary with NSUserDefaults. I read many posts on the topic in stackoverflow... I also found one option that worked; however unfortunately it worked only once and then it started to save (null) only. Does anybody have a hint?

Thanks

Code to save:

[[NSUserDefaults standardUserDefaults] setObject:[NSKeyedArchiver archivedDataWithRootObject:dictionary] forKey:@"Key"];
[[NSUserDefaults standardUserDefaults] synchronize];

Code to load:

NSMutableDictionary *dictionary = [[NSMutableDictionary alloc]init];
NSData *data = [[NSUserDefaults standardUserDefaults]objectForKey:@"Key"];
dictionary = [NSKeyedUnarchiver unarchiveObjectWithData:data];

Code to add Objects to the NSMutableDictionary:

[dictionary setObject:[NSNumber numberWithInt:0] forKey:@"Key 1"];
[dictionary setObject:[NSNumber numberWithInt:1] forKey:@"Key 2"];
[dictionary setObject:[NSNumber numberWithInt:2] forKey:@"Key 3"];

Code to NSLog() values:

for (NSString * key in [dictionary allKeys]) {
    NSLog(@"key: %@, value: %i", key, [[dictionary objectForKey:key]integerValue]);
}

And also the keys are (null):

NSLog(@"%@"[dictionary allKeys]);
Venk
  • 5,949
  • 9
  • 41
  • 52
user1940136
  • 343
  • 6
  • 12

1 Answers1

10

From Apple's documentation for NSUserDefaults objectForKey:
The returned object is immutable, even if the value you originally set was mutable.

The line:

dictionary = [NSKeyedUnarchiver unarchiveObjectWithData:data];

discards the previously created NSMutableDictionary and returns a NSDictionary.

Change the loading to:

NSData *data = [[NSUserDefaults standardUserDefaults]objectForKey:@"Key"];
dictionary = [NSKeyedUnarchiver unarchiveObjectWithData:data];

Complete example, there is also no need to use NSKeyedArchiver in this example:

NSDictionary *firstDictionary = @{@"Key 4":@4};
[[NSUserDefaults standardUserDefaults] setObject:firstDictionary forKey:@"Key"];

NSMutableDictionary *dictionary = [[[NSUserDefaults standardUserDefaults] objectForKey:@"Key"] mutableCopy];

dictionary[@"Key 1"] = @0;
dictionary[@"Key 2"] = @1;
dictionary[@"Key 3"] = @2;

for (NSString * key in [dictionary allKeys]) {
    NSLog(@"key: %@, value: %@", key, [dictionary objectForKey:key]);
}

NSLog output:
key: Key 2, value: 1
key: Key 1, value: 0
key: Key 4, value: 4
key: Key 3, value: 2

zaph
  • 111,848
  • 21
  • 189
  • 228
  • 1
    Happy New Year Zaph: many thanks for your help. I finally succeeded to make it work (through [NSKeyedArchiver archiveRootObject:counts toFile:path]; /[NSKeyedUnarchiver unarchiveObjectWithFile:path]). Neverthless I have a question on your answer, because I couldn’t make it work with NSUserDefaults. You proposed to change the loading to: NSData *data = [[NSUserDefault standardUserDefaults]objectForKey:@"Key"]; dictionary = [NSKeyedUnarchiver unarchiveObjectWithData:data]; I did that but it doesn’t work. Did you really mean this or did you forget to edit my initial input? – user1940136 Jan 01 '13 at 16:48
  • My answer was somewhat generic, rename and fix for your circumstances. The idea is once you can archive to NSData you have something that can be saved/restored by `NSUserDefaults`. – zaph Jan 01 '13 at 16:54