Core data: dependent keys

21 ottobre 2006

Simple problem: I want to update an attribute dependent on other attributes. Solution: setKeys:triggerChangeNotificationForDependentKey:. A not so simple problem: for speed issues, I want to cache the dependent keys and do some other stuf (refresh a view and so on).

In the following exampe I have a NSManagedObject rectangle with two attributes width and height. I have a dependent key, area and I want to refresh a view. First I declare my dependent key in initialize. Second, in awakeFromInsert, I take care to add the object as an observer of its ‘fake’ property updateProperties. Remember to remove it in didTurnIntoFault ! Also reset all transient attributes (like area) for clearness. In awakeFromFetch remember to call updateProperties, otherwise you’d find yourself with uninit’ed transient data after a fetch. Third, implement updateProperties. Important note: you MUST add the object as an observer to its fake property, otherwise, unless you bind it to some UI element, the property won’t be observed and won’t fire the update of the (sub)dependent keys (area, in this case). I wonder if there is a better way to do this.

+ (void) initialize
{
[self setKeys:[NSArray arrayWithObjects:@”width”,@”height”,nil] triggerChangeNotificationsForDependentKey:@”updateProperties”];}

– (void) awakeFromInsert
{
[super awakeFromInsert];[self addObserver:self forKeyPath:@”updateProperties” options:(NSKeyValueObservingOptions)NSKeyValueChangeKindKey context:NULL];
[self updateProperties];
}

– (void) awakeFromFetch
{
[super awakeFromFetch];
[self updateProperties];
}

– (void)didTurnIntoFault
{
[self removeObserver:self forKeyPath:@”updateProperties”];
[self setValue:[NSNumber numberWithDouble:0] forKey:@”area”];
[super didTurnIntoFault];
}

– (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
[self updateProperties];
[[NSNotificationCenter defaultCenter] postNotificationName:@”refreshSectionView” object:self];
}

– (BOOL) updateProperties
{
double width, height;
double area;

width=[[self valueForKey:@”width”]doubleValue];
height=[[self valueForKey:@”height”]doubleValue];
area=width*height;

[self setValue:[NSNumber numberWithDouble:area] forKey:@”area”];

return YES;
}/

Go top