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 protected]) 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: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to [email protected]
