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 NSMutableArray
s 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:
- Key-value observing works as expected (there are several cases where observing an NSMutableArray leads to not-what-you-want behavior)
- 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.