Re: Limited-access, KVO-compliant mutable array?
Re: Limited-access, KVO-compliant mutable array?
- Subject: Re: Limited-access, KVO-compliant mutable array?
- From: Quincey Morris <email@hidden>
- Date: Tue, 10 Jul 2012 23:45:53 -0700
On Jul 10, 2012, at 23:17 , Rick Mann wrote:
> Is this possible? My first thought is to make a read-only NSArray* property, but then it seems that addition or removal of elements to/from that property wouldn't get observed; i.e., an NSArray should never change its contents.
No, your first thought was correct.
It's not really an "array" property, it's an indexed to-many property**. As far as the client is concerned the value returned by the property could be (and sometimes is***) a proxy that doesn't permit the underlying NSMutableArray ivar (assuming there is on) to be mutated. Property type NSArray* is just an abstract behavior of the returned object. (Remember that NSArray isn't a concrete class.)
All that's required is that the indexed to-many property be mutated (by objects which *are* allowed to mutate it) in a KVO-compliant manner****. In that case, observers of the property will be notified.
** It's possible, though perhaps less usual, for a NSArray* property to be a to-one property with an array value. Semantically, it's a different kind of property (an attribute rather than a relationship), but there's no syntactic difference. Warning: The distinction can cause your brain to hurt.
*** Here's how you get a immutable proxy to an indexed to-one property:
a. Implement the countOf<Key> and objectIn<Key>AtIndex: methods in the class with the property.
b. Have clients of the class invoke 'valueForKey: @"<key>"' on an instance of the class with the property.
c. DO NOT implement a getter for the property "<key>". Doing so will cause infinite recursion when it's accessed. (This is one of KVC's most annoying defects.)
**** There isn't AFAIK a really easy way to prevent clients that aren't supposed to mutate the property from just invoking 'mutableArrayValueForKey: @"<key>"' by themselves.
One alternative approach is to use *two* property names: <privateKey> and <publicKey>.
You can then have <publicKey>'s getter return '[self valueForKey: @"privateKey"]'. That solves the infinitely-recursing-getter problem, but still returns an immutable observable proxy.
You can then also implement the custom add/remove KVC accessors for <publicKey> to throw an exception. Objects that *are* permitted to mutate the array will therefore need to know privateKey. (Likely, only instances of the implementing class are the only ones allow, so they know privateKey anyway.)
A second alternative approach is write your own mutable and immutable array proxies (subclasses of NSArray) instead of using the ones provided by KVC. It isn't terribly hard.
A third alternative approach is simply to trust your class's clients to respect the mutability rules of your class API. :)
_______________________________________________
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