What's the best way to use Obj-C 2.0 Properties with mutable objects, such as NSMutableArray?

I have an Obj-C 2.0 class that has an NSMutableArray property. If I use the following code, then the synthesised setter will give me an immutable copy, not a mutable one:

@property (readwrite, copy) NSMutableArray *myArray;

Is there any reason that Apple didn't implement the following syntax?

@property (readwrite, mutablecopy) NSMutableArray *myArray;

Since we don't have mutablecopy, what's the best way to handle this (seemingly common) situation? Should I just write my own setter that does a -mutableCopy?


Solution 1:

I ran into the same problem some time ago and found a document on the Apple Developer Connection recommending to provide your own implementation of the setter. Code sample form the linked document:

@interface MyClass : NSObject {
    NSMutableArray *myArray;
}
@property (nonatomic, copy) NSMutableArray *myArray;
@end

@implementation MyClass

@synthesize myArray;

- (void)setMyArray:(NSMutableArray *)newArray {
    if (myArray != newArray) {
        [myArray release];
        myArray = [newArray mutableCopy];
    }
}

Solution 2:

It's not common to pass around NSMutableArrays in Cocoa. Standard Cocoa practice would be to implement the key-value coding compliant methods for an indexed to-many property. This has two benefits:

  1. Key-value observing works as expected (there are several cases where observing an NSMutableArray leads to not-what-you-want behavior)
  2. The implementation of your data structure is hidden because you expose mutating methods (e.g. -[MyObject insertObjectInMyProperty:(id)newObject atIndex:(NSUInteger)i] , not the data structure itself.

Solution 3:

As said before, the right way to do it is not to make the mutable array a property. There's a great explanation of what you should implement to be KVC compliant here.