Reputation: 2475
I’d like to change object get from NSUserDefaults.
But when executing following code, the app crash with error message:
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '-[__NSCFDictionary setObject:forKey:]: mutating method sent to immutable object’
I have this code.
NSUserDefaults* pref = [NSUserDefaults standardUserDefaults];
NSMutableArray* data = [[NSMutableArray alloc]init];
data = [[pref objectForKey:@"Data"] mutableCopy];
for (NSArray* array in data) { //make object mutable
[array mutableCopy];
for (NSDictionary* dic in array) {
[dic mutableCopy];
}
}
[data[0][1] setObject:@"YES" forKey:@"isChecked"]; //for example
[pref setObject: data forKey: @"Data"];
[pref synchronize];
The structure of data:
NSMutableArray* arr1 = [@[[@{@"name":@"abc", @"isChecked":@"YES"} mutableCopy], [@{@"name":@"def", @"isChecked":@"NO"} mutableCopy]] mutableCopy];
NSMutableArray* arr2 = [@[[@{@"name":@"ghi", @"isChecked":@"NO"} mutableCopy], [@{@"name":@"jkl", @"isChecked":@"YES"} mutableCopy]] mutableCopy];
NSMutableArray* data = [@[arr1, arr2] mutableCopy];
[userDefaults setObject: data forKey: @"Data"];
How do I fix it to change object in NSArray
or NSDictionary
get from NSUserDefaults
?
Upvotes: 1
Views: 775
Reputation: 42977
[array mutableCopy]
will create a mutable copy of the array and returns it. You are not assigning it to the variable again. This will resolve your issue i guess.
array = [array mutableCopy];
similarly
dic = [dic mutableCopy];
Upvotes: 0
Reputation: 114818
You have the right idea - the objects returned from NSUserDefaults
are immutable, and you need to use mutableCopy
to get a mutable copy. However, your implementation is flawed.
mutableCopy
returns a new, mutable copy of the object. It does not make the existing object mutable. You are simply ignoring the mutable copy that you are creating.
As you want to mutate the data in your arrays, you can't use enumeration or you will get an error that the object was mutated while enumerating, so you will need to access the arrays by index -
NSUserDefaults* pref = [NSUserDefaults standardUserDefaults];
NSMutableArray* data = [[pref objectForKey:@"Data"] mutableCopy];
for (int i=0;i<data.count;i++) {
NSMutableArray *mArray = [data[i] mutableCopy];
for (int j=0;j<mArray.count;j++) {
NSMutableDictionary *mDictionary=[mArray[j] mutableCopy];
mDictionary[@"SomeKey"]=@"SomeValue";
mArray[j]=mDictionary;
}
data[i]=mArray;
}
[userDefaults setObject: data forKey: @"Data"];
Upvotes: 5