Re: NSArrayController + KVO + Core Data Question
Re: NSArrayController + KVO + Core Data Question
- Subject: Re: NSArrayController + KVO + Core Data Question
- From: Markus <email@hidden>
- Date: Tue, 24 Aug 2010 00:00:25 +0200
Hi,
there are two possible solutions for your problem:
nr.1: observe the NSManagedObjectContext via
NSManagedObjectContextObjectsDidChangeNotification
nr.2: observe arrangedObjects of your NSArrayController (as stated
above, this is possible)
When you are recieving the notifications (either via nr1s
NSNotificationCenter or in nr2s
observeValueForKeyPath:ofObject:change:context:) in your custom control
you have the chance to update your model. For nr2s approach you have to
track the objects you are observing (via a private property of your
custom view) and update it correspondingly. Additionally you probably
want to observe keypaths of your model (to get notifications if
individual propertys of your item changed.
Pseudocode:
@interface View
{
NSArray *observedItems;
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object
change:(NSDictionary *)change context:(void *)context
{
if ( context == kMyCollectionChangedContext ) {
NSArray *changedItems = [ object valueForKey:keyPath ];
NSArray *newItems = all items from changedItems but not in
observedItems;
NSArray *removedItems = all items not in changedItems but in
observedItems;
[ self tearDownObservationOfItems:removedItems ];
[ self addObservationOfItems:newItems ];
self.observedItems = newItems;
[ self updateUI ];
}
else if ( context == kMyIndividualPropertyChangedContext ) {
track which individual property changed and update UI (in your
case modify the corresponding layer)
}
}
- (void)addObservationOfItems:(NSArray*)newItems
{
for ( id item in newItems ) {
[ item addObserver:self keyPath:theKeyPathForIndividiualProperty
options:0 context:kMyIndividualPropertyChangedContext ];
}
}
- (void)tearDownObservationOfItems:(NSArray*)oldItems
{
for ( id item in oldItems ) {
[ item removeObserver:self
forKeyPath:theKeyPathForIndividiualProperty ];
}
}
You can easily add additional individual properties in
addObservationOfItems:, just add your view as an observer for the
corresponding keypath.
Regards, Markus
Am 23.08.10 00:55, schrieb Ajay Sabhaney:
Hello all,
In my Core Data based application, I have an NSArrayController, and it was necessary for me to receive a KVO notification when either a new item was added to the array controller, or removed from the array controller. By looking in to some forums, I found out that I cannot do this by observing the arrangedObjects property in NSArrayController - some say this is a bug. So instead, I binded the contentArray to a mutable array that I used to add and removed objects to or from. In addition, I added array accessors for the mutable array so that the KVO would work as expected. This now works beautifully, and I receive KVO notifications for object insertion and removal, as well as have the ability to see which objects were added or removed when observeValueForKeyPath:ofObject:change:context: is invoked.
However, in doing this, I lost some of the functionality that came for free with Core Data: undo/redo, load/save, etc. I suppose this is because Core Data makes the changes to arrangedObjects (and the mutable array binded to contentArray is not touched), and I am no longer observing arrangedObjects. I manually added some undo/redo functionality in the array accessors, but now thinking about how to do loading documents. I would like to stay away from observing arrangedObjects, as then I would receive two KVO notifications for adding and removing objects in to the NSArrayController (one through the contentArray observation and one through the arrangedObjects observation).
I also thought about subclassing NSArrayController so that addObject: performs a KVO notifications like so:
[self willChange:NSKeyValueChangeInsertion valuesAtIndexes:indexes forKey:@"arrangedObjects"];
[super addObject:object];
[self didChange:NSKeyValueChangeInsertion valuesAtIndexes:indexes forKey:@"arrangedObjects"];
This would alleviate the need to use the contentArray property. However, I am assuming this would generate two KVO events - the new insertion notification (NSKeyValueChangeInsertion), and the existing change notification (NSKeyValueChangeSetting). I would like to avoid this.
So my question is, is there an easy and efficient way to achieve what I am trying to do?
Thank you in advance.
Ajay
_______________________________________________
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
_______________________________________________
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