Take the 2-minute tour ×

I am receiving this error: '-[__NSCFArray insertObject:atIndex:]: mutating method sent to immutable object'

In the ViewDidLoad I initialized my array:

id object = [[NSUserDefaults standardUserDefaults] objectForKey:@"array"];

    if (object) 
        locationArray = object;
        NSLog(@"retrieved", object);
        locationArray = [[NSMutableArray alloc] init];

Then, I am trying to add the data to locationArray:

            ABMultiValueRef multi = ABRecordCopyValue(person, property);
            NSUserDefaults *locatie = [NSUserDefaults standardUserDefaults];

            // Set up an NSArray and copy the values in.
            NSArray *theArray = [(id)ABMultiValueCopyArrayOfAllValues(multi) autorelease];
            //everything goes fine the first time, but the second time i receive an error after at this code:
            [locationArray addObject:theArray];

            [locatie setObject:locationArray forKey:@"array"];

Every first time I select an address everything is fine. But every second time I am receiving that error. What did I do wrong?

share|improve this question
You posted your code (good) but you left out a good description of what's going wrong (bad). Are you seeing an exception? Does your array not show up when you read it? –  Joshua Nozzi Sep 15 '10 at 15:13
Where does your nameArray come from? Also note that you always get immutable objects from the user defaults, even if you put mutable objects in. –  Sven Sep 15 '10 at 15:20
If you have a new question, don't edit you old questions on SO. Always create a new post. –  Nikolai Ruhe Sep 16 '10 at 10:36
add comment

3 Answers

up vote 2 down vote accepted
NSString *fname = (NSString *)ABRecordCopyValue(person, kABPersonFirstNameProperty);
NSMutableString *lname = (NSMutableString *)ABRecordCopyValue(person, kABPersonLastNameProperty);

What makes you think ABRecordCopyValue is going to return a mutable string here?

Just telling the compiler that it will return a mutable string (which is all “(NSMutableString *)” does) doesn't mean it will. If the Address Book documentation doesn't specify that this will return a mutable string, assume it won't and create a mutable string yourself.

Speaking of which…

NSMutableString *name = [[NSMutableString alloc] init];

Here's the string you should be appending to. You don't need lname to be mutable, because this string is mutable.

NSMutableString *space = @" ";
fname = [fname stringByAppendingFormat:space];
fname = [fname stringByAppendingFormat:lname];

By doing this, you waste the mutable string you created. You are creating two intermediate immutable strings here, not appending to the mutable string.

name = fname;

And here, you throw away the mutable string entirely (and thereby leak it since you never released it), replacing it with the immutable string you got from your series of stringByAppendingFormat: messages.

What you should do is send the name mutable string an appendFormat: message, passing both the first and last name strings. You don't need the space string; you can include that in the format string.

See also the NSMutableString docs.

[nameArray addObject:fname];

At no point prior to this statement have you created an NSMutableArray object and stored its pointer in the nameArray variable. Not in any code you've shown, anyway.

Until you do that, this variable holds nil, the pointer to no object. The addObject: message does nothing because that's what messages to nil do: Nothing. Logging the array you don't have produces “(null)” because that's the description of nil.

    if (nameArray == nil) {

You aren't showing any code that retrieves from user defaults. Even if you did, it would return an immutable array as Sven said; you would have to make a mutable copy.

This is the best I can do without a description of the problem. We may be able to provide more and better suggestions if you edit your question to tell us what happens when you run the above code, and not just what doesn't happen.

share|improve this answer
add comment

The problem occures when you get the locationArray from the NSUserDefaults and try to insert some object ([locationArray addObject:theArray];). The object you get from the NSUserDefaults is not mutable, so you have to create a mutable copy:

NSMutableArray* locationArray = [[NSUserDefaults standardUserDefaults] objectForKey:@"array"];

if (locationArray != nil)
    locationArray = [[locationArray mutableCopy] autorelease];
    locationArray = [NSMutableArray array];
share|improve this answer
add comment

And don't forget to check if fname is not nil before adding it to array

share|improve this answer
add comment

Your Answer


