Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 533
SmartTree Avatar asked Feb 12 '13 19:02

SmartTree


2 Answers

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.

like image 67
Lance Avatar answered Sep 21 '22 11:09

Lance


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

like image 26
aks.knit1108 Avatar answered Sep 19 '22 11:09

aks.knit1108