Question

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?

Was it helpful?

Solution

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.

OTHER TIPS

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];
    }
}

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.

Keep in mind that passing around a mutable array isn't really a common practice in Cocoa. You might use a private mutable array as internal storage, but create methods using plain NSArray objects to add or get objects out of it. This may be why there's no mutablecopy property declaration.

You'll have to write your own setter.

The right way to hold on to a NSMutableArray is with a retain property:

@property (nonatomic, retain) NSMutableArray *myArray;

You do not need to write your own setter or use copy. The copy property should be used with a NSArray that actually does need to be copied when the property is captured into another object. For example, if you assign a NSMutableArray object to a property that is of type NSArray with the copy property, then you do want to make a copy of the mutable array to "capture" it as an immutable property from that point forward.

And Marc has the right approach, one would not normally make NSMutableArray a part of the public API of your objects. If you do have a public property, it can be a NSArray with the copy property.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top