I have a sample managed object model depicted in the image below. What I would like to happen is this: When the object that is the value for the currency relationship in a Bar object is changed, to automatically have that same object be set as the currency relationship in all Foos that are related to that Bar through the foos relationship.
Am I right to understand that this can be done through KVO? My inclination was to start by adding this to the Foo.m:
+ (NSSet *)keyPathsForValuesAffectingCurrency {
return [NSSet setWithObject:@"bar.currency"];
}
but I can't figure out if this is right or how I would proceed further. Thanks for any advice.
The simplest way to observe changes in a Core Data store is by listening for one of the various notifications that are posted when changes occur within Core Data. For example, you can listen for the NSManagedObjectContext.
An entity is represented by an instance of the NSEntityDescription class. This class provides access to a wide range of properties, such as its name, the data model it is defined in, and the name of the class the entity is represented by.
Inverse relationships enable Core Data to propagate change in both directions when an instance of either the source or destination type changes. Every relationship must have an inverse. When creating relationships in the Graph editor, you add inverse relationships between entities in a single step.
There are several possible solutions:
What you want to accomplish is certainly possible and KVO can take care of this. You would just have to implement a couple of things.
You can add your object as an observer when your object is awakening.
- (void) awakeFromInsert {
[super awakeFromInsert];
[self addObserver:self forKeyPath:@"bar.currency" options:NSKeyValueObservingOptionNew context:nil];
}
// Repeat for awakeFromFetch
Do note that this works in this case since this is a to-one relationship.
Update the value of currency
when a notification for bar.currency
is fired
- (void) observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context
{
if( [keyPath isEqualToString:@"bar.currency"] ) {
[self setValue:[self valueForKeyPath:@"bar.currency"] forKey:@"currency"];
}
// The rest of your KVO logic ...
}
As you pointed out, this can also be done by implementing dependent keys
+ (NSSet *)keyPathsForValuesAffectingCurrency {
return [NSSet setWithObject:@"bar.currency"];
}
In this case, you'd instead have to observe @"currency"
. In your observeValue...
method you'd have to check for this key instead. Finally, you'd have to set the value using setPrimitiveValue:forKey
as opposed to setValue:forKey:
. This is because the latter would cause a new notification and result in an endless loop.
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