SmartTree
SmartTree

Reputation: 1471

NSMutableArray of NSMutableArrays. Mutating method sent to immutable object

I have NSMutableArray of NSMutableArrays:

 NSMutableArray *array = [[NSMutableArray alloc]init];

        for (int i = 0; i < 5; i++)
        {
            NSMutableArray *miniArray = [[NSMutableArray alloc]init];

            for (int k = 0; k < 30; k++)
            {   
                [miniArray addObject:@"0"];
            }
            [array addObject:miniArray];
        }

Then, when I try to do this:

 [[array objectAtIndex:packIndex]replaceObjectAtIndex:index withObject:@"1"];

it crashes with: [__NSCFArray replaceObjectAtIndex:withObject:]: mutating method sent to immutable object'

Why ? How to fix ? Thanks !

UPD: I save this array in NSUserDefaults:

[defaults setObject:array forKey:@"mainArray"];

Then, I read it in the other class:

array = [[NSMutableArray alloc]initWithArray:[[NSUserDefaults standardUserDefaults] objectForKey:@"mainArray"]];

Also, I must to mention that sometimes the code runs well and it changes "0" to "1". But it also crashes sometimes. So I cant see the logic, why it works fine or why it crashes sometimes.

Upvotes: 7

Views: 7153

Answers (3)

aks.knit1108
aks.knit1108

Reputation: 1305

Values returned from NSUserDefaults are immutable, even if you set a mutable object as the value. For example, if you set a mutable string as the value for "MyStringDefault", the string you later retrieve using stringForKey: will be immutable.

Instead, make a mutableCopy of the array you retrieve from NSUserDefaults, add your object, then set your new array back in.

see this link: https://developer.apple.com/documentation/foundation/nsuserdefaults

Upvotes: 6

Lance
Lance

Reputation: 9012

The problem is that when you read the array out of NSUserDefaults, the mini-arrays are not automatically NSMutableArrays.

Try this:

array = [[NSMutableArray alloc]initWithArray:[[NSUserDefaults standardUserDefaults] objectForKey:@"mainArray"]];
for(int i = 0; i < array.count; i++) {
    NSArray * tempArray = array[i];
    array[i] = [tempArray mutableCopy];
}

Edit: Best Coder's answer explains why this is. Objects stored in NSUserDefaults are stored as immutable versions, basically NSUserDefaults is a plist and there is no flag marking an array as mutable/immutable so when you read them back out, they are assumed to be immutable.

Upvotes: 26

Chris C
Chris C

Reputation: 3251

Try using more verbose code:

NSMutableArray *tempArray = [array objectAtIndex:packIndex];
[tempArray replaceObjectAtIndex:index withObject:@"1"];

Upvotes: -5

Related Questions