0

So I have a property NSMutableArray *grades. At the only place where I set this property, I am doing this:

NSMutableArray *array = [[NSMutableArray alloc] init];
self.grades = array;    
[array release];
[self.grades addObject:@"20"];

The last statement generates an exception: -[NSCFArray insertObject:atIndex:]: mutating method sent to immutable object'.

What in the world am I missing?

1
  • Edited to show the correct property name (it's grades, not stuff). Sorry about that. Commented Jul 10, 2010 at 20:52

4 Answers 4

8

It sounds like the property is set to copy, which means the synthesized accessor makes an immutable copy of the array

Sign up to request clarification or add additional context in comments.

Comments

6

Make sure grades is a NSMutableArray.

Edit:

copy returns an immutable copy, so you can't make changes. From Apple's Objective-C docs:

Copy

If you use the copy declaration attribute, you specify that a value is copied during assignment. If you synthesize the corresponding accessor, the synthesized method uses the copy method. This is useful for attributes such as string objects where there is a possibility that the new value passed in a setter may be mutable (for example, an instance of NSMutableString) and you want to ensure that your object has its own private immutable copy. For example, if you declare a property as follows:

Although this works well for strings, it may present a problem if the attribute is a collection such as an array or a set. Typically you want such collections to be mutable, but the copy method returns an immutable version of the collection. In this situation, you have to provide your own implementation of the setter method, as illustrated in the following example.

Copying the entire collection on assignment is a heavy operation. Are you sure you don't want to retain the collection, or just assign it?

If you really want a mutable copy, then write your own setter as the docs suggest.

- (void)setGrades:(NSMutableArray *)array {
    // make shallow/deep copy here, and assign to `grades`, not `self.grades`
}

3 Comments

It is: @property (nonatomic, copy) NSMutableArray *grades;
change it to (nonatomic, retain)
why do you need to copy it in the first place? From the code in the original post you allocated the array and passed it to the instance variable grades, then you released the original object. This is the same behaviour as just using a retain call.
0

What is grades declared as?

From the looks of the error message your declaring grades as an NSArray and while this is valid it does mean that you lose the mutability of the array.

To maintain the array as mutable you'll need to declare grades as an NSMutableArray as well.

edit:

In light of your edit the reason could be that your using the copy keyword in the property, this would mean that when your assigning the array using self.grades the synthesised setter method makes an immutable copy of array

1 Comment

The class grades is statically declared as makes no difference to what the object actually is. It will not make it immutable. You'd get a warning at compile time, but definitely not a runtime error.
0

self.grades probably returns an NSArray if declared as @property NSArray* grades seeing this the compiler freaks and does not want to support addObject: method. You have 2 options

  1. cast it like [(NSMutableArray*)self.grades addObject:].
  2. add the object before assigning the array.

1 Comment

This is a runtime exception. The compiler would merely produce a warning.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.