I'm relatively new to Core Data and KVC, but I would like some pointers on registering listeners for changes in Core Data objects. Here's the situation:
I have one NSManagedObject
called Patient
and another called Medication
. A Patient
may have many Medications
, and a Medication
has a startOn
and endOn
dates.
I'd like to somehow listen for changes to the endOn
property of all Medication
objects. When a change occurs, I would like to schedule a local notification on the iOS device. I've worked with local notifications before, but don't know where to put the code for it in this context.
Do I create the scheduling code in the App Delegate and somehow register the App Delegate to listen for changes in Medication
objects? Does this need to be attached to the NSManagedObjectContext
?
How is this done? Pointers would be much appreciated!
Thanks!
With Key Value Observing, you need some instance to do the observing. Sometimes that can be the same object that calls -setEndOn: on Medication; sometimes it might have to be something else. Let's assume that your app has a MedicationManager class - of which one instance is created. And, further assume that MedicationManager has an instance method -createMedicationWithName:startOn:endOn: like this:
- (Medication*) createMedicationWithName:(NSString*)medName startOn:(NSDate*)startDate endOn:(NSDate*)endDate
{
// Create and configure a new instance of the Compound entity
Medication *newMedication = (Medication *)[NSEntityDescription insertNewObjectForEntityForName:@"Medication"
inManagedObjectContext:[self managedObjectContext]];
[newMedication setName:medName];
[newMedication setStartOn:startDate];
[newMedication setEndOn:endDate];
// Set up KVO
[newMedication addObserver:self
forKeyPath:@"endOn"
options:NSKeyValueObservingOptionNew
context:nil];
return newCompound;
}
- (void) observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context
{
if ([keyPath isEqualToString:@"endOn"])
{
// ... schedule local notification on the iOS device for (Medication*)object.
return;
}
}
Or something like that.
Note, when you delete a Medication, then you would want to removeObserver... Also, when launching your app, you would need to establish MedicationManager as observer for existing Medications. I think that this could be as simple as iterating over all Medications and calling addObserver for each. If you have many Medications, then you might want to do this in a more 'lazy' manner (i.e., in -awakeFromFetch).