KVO object properties within to-many relationship

2019-05-09 11:18发布

I have a Core Data to-many relationship consisting of Parent <--->> Child. I would like to setup a key-value observing mechanism such that when a property (e.g. firstName, lastName) on any of the Child objects changes it triggers a notification. When using the standard KVO syntax:

[self.parentObject addObserver:self forKeyPath:@"children" options:NSKeyValueObservingOptionNew context:NULL]

this only notifies when the relationship itself is modified (i.e. a Child object is added or removed from the relationship), rather than when a property of one of those Child objects changes. Obviously this is how it was designed to operate, so there's nothing wrong with that happening, but how can I instead use KVO to achieve my desired requirement?

Thanks in advance!

2条回答
何必那么认真
2楼-- · 2019-05-09 11:57

A bit of a late answer, but maybe it will be useful to someone who googles this.

You can setup an NSFetchedResultsController for the entity child with the predicate @"parent == %@", childand then add your controller as a delegate to that fetchedResultController. The delegate will be called when any of the properties of the child changes, as well as when they are added etc. An example code follows. I have also added a sort descriptor to sort the children by their name to the

...
NSFetchRequest* fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"Child"];
fetchRequest.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES]];

NSPredicate* predicate = [NSPredicate predicateWithFormat:@"parent = %@", parent];
self.fetchResultsController.fetchRequest.predicate = predicate;

self.fetchResultsController = [[NSFetchedResultsController alloc] 
     initWithFetchRequest:fetchRequest managedObjectContext:context 
     sectionNameKeyPath:nil cacheName:nil];

self.fetchResultsController.delegate = self;
...

Then you implement the delegate method

- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject
   atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type
  newIndexPath:(NSIndexPath *)newIndexPath {

And any other delegate method you need for your implementation (the documentation has a very good code snippet for this

查看更多
等我变得足够好
3楼-- · 2019-05-09 12:03

AFAIK there is no built-in way to observe collection object properties with a single line of code. Instead you have to add/remove observers when the object is inserted/removed from your collection.

An explanation and a sample project can be found over here: https://web.archive.org/web/20120319115245/http://homepage.mac.com/mmalc/CocoaExamples/controllers.html (See the "Observing a collection is not the same as observing the properties of the objects in a collection" section)

Update:
The Link broke - I changed it to an archive.org snapshot.

查看更多
登录 后发表回答