Using a mutable array to retrieve an array saved to NSUserDefaults and changing the value

115 views Asked by At

Values returned from NSUserDefaults are immutable, even if you set a mutable object as the value.

There is a problem about this that confuses me.

I save an NSArray (immutable) into user defaults with setObject:forKey: and then synchronize.

I delete the code for saving and I use an NSMutableArray to get the value I saved, via objectForKey:

I do some mutable operation on the mutable array. I use [[userDefaults standardUserDefaults] objectForKey:] to retrieve the array, and it's changed by my operation, and I synchronize.

But when I run the program again, the array is not changed!

Can I use the mutable class to receive a immutable class? It can be changed, and it appears in memory, and the value retrived from the user defaults was changed also. I don't know why. I synchronized, but the plist file was not changed. I don't know why.

code:

    //NSLog(@"Hello, World!");
    NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
    //NSArray *arr = @[@"1",@"2"];
    //[ud setObject:arr forKey:@"arr"];
    //[ud synchronize];
    NSMutableArray *arr = [ud objectForKey:@"arr"];
    NSLog(@"before %@",arr);
    NSLog(@"%@",[arr class]);
    [arr isKindOfClass:[NSMutableArray class]];
    [arr removeObjectAtIndex:0];
    NSLog(@"after %@",arr);
    BOOL ans = [ud synchronize];
    NSArray *arr2 = [ud objectForKey:@"arr"];
    NSLog(@"retrieve from ud %@",arr2);

console:

2013-12-02 11:42:46.791 NSUserDefaultsDemo[24447:303] before (
1,
2)
2013-12-02 11:42:46.792 NSUserDefaultsDemo[24447:303] __NSArrayM
2013-12-02 11:42:46.792 NSUserDefaultsDemo[24447:303] after (
2)
2013-12-02 11:42:46.793 NSUserDefaultsDemo[24447:303] retrieve from ud (
2)
1

There are 1 answers

5
juniperi On

You don't save your changes to NSUserDefaults as I thought.

This code works:

NSArray *arr = @[@"Object 1", @"Object 2"];
[[NSUserDefaults standardUserDefaults] setObject:arr forKey:@"testArr"];

NSMutableArray *mArr = [NSMutableArray arrayWithArray:[[NSUserDefaults standardUserDefaults] objectForKey:@"testArr"]];
[mArr removeObjectAtIndex:0];
[[NSUserDefaults standardUserDefaults] setObject:mArr forKey:@"testArr"];

Synchronize don't save your changes if you don't use setObject:forKey: method first. And btw, you don't need to call synchronize manually, only if you want to make sure that preferences gets saved when you quit your application etc.