Re: Use of mutableArrayValueForKey
Re: Use of mutableArrayValueForKey
- Subject: Re: Use of mutableArrayValueForKey
- From: Ken Thomases <email@hidden>
- Date: Sat, 18 Dec 2010 00:12:47 -0600
On Dec 17, 2010, at 3:42 AM, Giannandrea Castaldi wrote:
> I have a class with a NSMutableArray as readonly property and I need
> to execute an action when a new item is added to the array.
> I would like:
> - to use key-value observing on my NSMutableArray with the collection
> accessor pattern
> - to preserve the information hiding of my objects and then to change
> my current readonly property so that returns a NSMutableArray built
> with mutableArrayValueForKey:
>
> The way I've found is the following:
> 1 - define a private readwrite property with the plain NSMutableArray
>
> NSArray* myPrivateArray;
>
> @interface MyClass ()
> @property(nonatomic,retain) NSArray* myPrivateArray;
> @end
>
> 2 - in the init method initialize the private Array:
> ...
> self.myPrivateArray = [NSMutableArray array];
> ...
>
> 3 - redefine the public readonly property so that return a
> NSMutableArray built with mutableArrayValueForKey:
>
> - (NSMutableArray*)myArray {
> return [self mutableArrayValueForKey:@"myPrivateArray"];
> }
>
> Such a solution is a good practice?
> I could build also the proxy array in the init method, which solution is better?
In my opinion, neither. I feel (although not everybody agrees), that key-value coding is for dynamism where the key is part of data (like a NIB) or otherwise a variable. If you're using KVC with compile-time-constant keys, that's a code smell.
I would do the following:
* Use an NSMutableArray* instance variable. It should go without saying that instance variables should almost always be private.
* Make a read-only property whose type is NSArray* (not NSMutableArray*):
@property (readonly,retain) NSArray* myThings;
This provides a getter for non-mutating access. This property can be backed by the instance variable in the usual way. It's fine for the property's type to be narrower than the instance variable's. There's no need for two properties or anything like that. (Note: I have renamed this property to be a plural, which works better with the KVC naming conventions.)
* Implement the mutating indexed collection accessor methods <http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/KeyValueCoding/Concepts/AccessorConventions.html>:
One or both of:
-insertObject:inMyThingsAtIndex:
-insertMyThings:atIndexes:
One or both of:
-removeObjectFromMyThingsAtIndex:
-removeMyThingsAtIndexes:
I assume here that you only need to create the array once, at initialization. If you need to wholesale replace it, then you could add a private setter.
When your code mutates the array, it should go through the above mutating indexed accessor methods. That preserves KVO compliance. If your code needs to take action when the array is mutated, it would do so in those accessor methods.
If a client of your class needs to do dynamic KVC, then it can use -mutableArrayValueForKey: and get the proxy which will use those accessors, as appropriate. For example, an editable NSArrayController would use this.
I make an exception to my admonition against compile-time-constant KVC for a few high-level NSArray/NSMutableArray methods that would just be too tedious or error-prone to implement in terms of the indexed accessors, such as -filterUsingPredicate: or the -sort... methods.
Regards,
Ken
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden