Re: NSDocument updateChangeCount when using Bindings
Re: NSDocument updateChangeCount when using Bindings
- Subject: Re: NSDocument updateChangeCount when using Bindings
- From: Quincey Morris <email@hidden>
- Date: Thu, 6 Jan 2011 22:39:47 -0800
On Jan 6, 2011, at 18:01, Kevin Bracey wrote:
> MyDocument has a
> iVar = NSMutableArray *allScenes;
> @property( retain ) NSMutableArray *allScenes;
> @synthesize allScenes;
>
> In my nib I have a ArrayController bound to allScenes and it is hooked up to a Table and and selected Fields, it is adding and editing my Scene Objects great.
>
> I have these Saving and Loading from a Package using NSKeyArchiver, working great.
>
> How do I get the [MyDocument updateChangeCount:NSChangeDone]; to be called when I add or delete a allScenes object or edit one of there properties?
You're kinda Doing It Wrong™ and your problem with updating the change count is something of a side effect.
It's almost certainly wrong to expose a *mutable* array ivar as a public *mutable* array property, especially when the the property is synthesized. By doing this, you've allowed clients of your class to modify the property non-KVO-compliantly. (For example, '[document.allScenes addObject:...]' is allowed by your interface but is not compliant.) Currently it "works great", I'm guessing, because currently the *only* way the array gets changed is via the array controller, and the array controller brute-force-ensures KVO compliance on its own accesses. (For example, it adds to the array with something like '[[document mutableArrayValueForKey: @"allScenes"] addObject:...]', which is compliant.) If you later add other ways of changing the array, you're leaving yourself open to a compliance problem, and it's likely to be an extremely hard bug to track down.
The easiest way to fix this is:
1. Declare the property as '@property (retain) NSArray *allScenes;'.
Counter-intuitively, this won't break your array-controller-initiated updates, since the array controller doesn't know the property type anyway. If you read the comments for 'mutableArrayValueForKey:' in NSKeyValueCoding.h carefully, you'll see that without further intervention KVC will go ahead and update the mutable array anyway (case #3). But that's not what you really want, so also ...
2. Define mutable array accessors in your document subclass. Something like:
- (void) insertObject: (id) object inAllScenesAtIndex: (NSUInteger) index {
[allScenes insertObject: object atIndex: index];
}
and a similar one for removing objects. (Such methods are inherently KVO compliant.) As a result, every object insertion and removal will be done via your custom accessors, and -- magically -- you will now have convenient places to update the document change count.
3. If code needs to update the array property other than via KVC, you can expose your custom accessors as public methods. As I said, they're inherently KVO compliant, so this solves the original problem in your implementation. Or, clients of the class can use 'mutableArrayValueForKey:' directly. Either way, they'll be forced to do it right, and prevented from doing it wrong.
_______________________________________________
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