I have an iPad app that has a UITableViewController
that implements the NSFetchedResultsControllerDelegate
. (Mostly using the CoreDataTableViewController
code from the Stanford iOS classes.)
I have a secondary model object (self.locations
) that is an array of Location
objects which is a subclass of NSManagedObjects
. This array drives the content of a UISegmentedControl
that filters my main fetchedResultsContoller
.
It is possible to modify the contents of self.locations
via a popover. I want to set up some sort of observing so that my main UITableViewController
can watch for changes in the objects stored in self.locations
and reload the UISegmentedControl
if necessary.
This might also result in a reload of the main data in the table, so I want to be careful to not reload on every little modification.
I think I understand how to setup KVO on a single NSManagedObject
but I'm not sure how to do it on object contained in an array. I understand that I can use another NSFetchedResultsController, but my self.locations
object does not drive a second UITableView, so I'm not sure it makes sense.
It is pretty straight-forward to observe a one-to-many relationship if all you want to know if objects are added, removed, replaced, or re-ordered. In fact, it is done exactly the same way as with a normal object:
[self addObserver:self
forKeyPath:@"locations"
options:0
context:NULL];
Then implement the following to receive notifications (partially copied from Apple docs):
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context {
if ([keyPath isEqual:@"locations"]) {
// Your custom code here.
}
// Be sure to call the superclass's implementation *if it implements it*.
[super observeValueForKeyPath:keyPath
ofObject:object
change:change
context:context];
}
Don't forget to stop observing at some point:
[self removeObserver:self forKeyPath:@"locations"];
And, although you didn't ask, if you want to know if any of the objects contained in the relationship have changed (and not just the NSSet that you are watching here) then you have to observe the individual objects.
EDIT
Per your comment, you do want to observe the individual objects. This is fairly straight-forward for "normal" objects, but a managed object takes a bit more work because you have to observe the individual keys in the object, which would look something like this:
- (void)observeManagedObject:(NSManagedObject *)myObject {
NSArray *myObjectKeys = [[[myObject entity] attributesByName] allKeys];
for (NSString *key in myObjectKeys) {
[myObject addObserver:self
forKeyPath:key
options:0
context:nil];
}
}
And then you observe all of the NSManagedObjects in the array like this:
for (NSManagedObject *object in myArray) {
[self observeManagedObject:object];
}
Do the reverse to stop observing the keys on the managed object!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With