• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: NSArrayController Frustration
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: NSArrayController Frustration


  • Subject: Re: NSArrayController Frustration
  • From: Steve Weller <email@hidden>
  • Date: Sun, 25 Nov 2007 21:30:46 -0800


On Nov 25, 2007, at 8:50 PM, Chris Hanson wrote:

On Nov 24, 2007, at 5:58 PM, David Carlisle wrote:

I am expecting that when I do [docArray addObject:x] that the array controller will observe the change and do a reloadData on the NSTableView. That isn't happening.

Your expectation is incorrect. What your NSArrayController is bound to is not the docArray *object* but the docArray *property* (or key) of your NSWindowController subclass.


There are a few different ways you can resolve this. You've proposed one yourself -- to do all manipulations via the NSArrayController -- which I do not recommend because it violates encapsulation and leads people to mix model and controller level code unnecessarily.

I. Savant suggested that you surround changes to docArray with {will,did}ChangeValueForKey: pairs to ensure KVO change notifications. I do not recommend this because it *also* violates encapsulation -- you're mixing in "maintenance" code with the code that uses the property. This is fragile in that it will be easy to forget a spot, post the wrong notification due to a typo, etc.

So, since I've shot down the first two ideas posted, what *do* I recommend? One of the following:

(1) Make your manipulations of the docArray property specific, by implementing the appropriate ordered-relationship-KVC accessor methods:

  - (NSUInteger)countOfDocArray
  - (id)objectInDocArrayAtIndex:(NSUInteger)index;
  - (void)insertObject:(id)object inDocArrayAtIndex:(NSUInteger)index;
  - (void)removeObjectFromDocArrayAtIndex:(NSUInteger)index;

And so on. The above four are the minimum methods to implement, beyond -docArray and -setDocArray: -- the full naming pattern is described in the Key-Value Coding Programming Guide, and it's also documented in <Foundation/NSKeyValueCoding.h> under -valueForKey: and -mutableArrayValueForKey:.

Then, instead of manipulating docArray directly, manipulate it only using the above methods (which are allowed to manipulate the array directly). Key-Value Observing -- used by bindings -- will automatically do the right thing and cause the above methods to post appropriate observer notifications for every manipulation of the docArray property that occurs via them.

(2) Whether or not you do #1 above, you can just use the NSMutableArray that you get back from [self mutableArrayValueForKey:@"docArray"] to manipulate the array. It will not actually return your own array; instead, it will return a proxy object that also causes the appropriate KVO notifications to be posted for every manipulation of your own array. If you *do* do #1 above, it will even cause the methods you have written to be invoked.

I'm sure this seems complicated -- "I just want to observe an array!" you're no doubt saying -- but if you remember that observation and (therefore) binding happens at the property rather than the object level, it will make a lot more sense. As long as you have the appropriate methods implemented for the type of property you want to manipulate, and you manipulate the property through those methods, its implementation will be irrelevant.

-- Chris

I have an example of my running into a similar problem and solving it in a similar way. See items 29 through 32 here:


http://www.bagelturf.com/cocoa/rwok/rwok4/index.html

In my case I had an array of dictionaries whose elements were bound to table columns. By implementing the methods that Chris describes in (1) above, the magic (really just advanced technology) occurs and changes are automatically seen and reflected in the interface.

The trick to understanding KVO is to realize that there is no such thing as "observing" going on. "Observing" describes the effect experienced, not the way the effect is implemented. As Chris points out, it's the properties (via keys, as in *Key* Value Observing) that are observed, not the objects themselves -- there is no Object Observing.

KVO is an active process: changes to properties are actively propagated to observers via messages. In the case of an array, changing the members does nothing for an observer of the array because the members are not actively involved in the observation. Method (1) above provides for manipulation of the array by implementing observable properties and hence the messages get to the observers. Method (2) just hides all of that from you via a proxy object.

_______________________________________________

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


  • Follow-Ups:
    • Re: NSArrayController Frustration
      • From: David Carlisle <email@hidden>
References: 
 >NSArrayController Frustration (From: David Carlisle <email@hidden>)
 >Re: NSArrayController Frustration (From: Chris Hanson <email@hidden>)

  • Prev by Date: Re: IKImageBrowser performance issues
  • Next by Date: Re: Multiple applications, one NSUserDefaults object?
  • Previous by thread: Re: NSArrayController Frustration
  • Next by thread: Re: NSArrayController Frustration
  • Index(es):
    • Date
    • Thread