NSManagedObject subclass accessor pattern mystery?
NSManagedObject subclass accessor pattern mystery?
- Subject: NSManagedObject subclass accessor pattern mystery?
- From: Michael B Johnson <email@hidden>
- Date: Mon, 29 Sep 2008 21:44:38 -0700
So I have a CoreData app (10.5.5, 64 bit only) that has a
NSManagedObject that has an NSColor* that is part of its data model.
Because this color is actually a computed value that we want to cache,
it is declared as a property:
@property (retain) NSColor* color;
but since we may need to calculate it, we also map it to an instance
variable _color:
@synthesize color = _color; // we actually implement both setter and
getter - should we stil declare this?
- (NSColor*)color {
[self willAccessValueForKey:@"color"];
if (!_color) {
NSImage* img = [self thumbnail];
[self setColor:[img BW_representativeColor]];
}
[self didAccessValueForKey:@"color"];
return _color;
}
- (void)setColor:(NSColor*)c {
[self willAccessValueForKey:@"color"];
if (c != _color) {
[self willChangeValueForKey:@"color"];
[_color release];
_color = [c copy];
[self didChangeValueForKey:@"color"];
}
[self didAccessValueForKey:@"color"];
}
So I understand that the willAccessValueForKey: gives CoreData the
opportunity that when the color accessor is called, CoreData can
sneakily go in and set _color for me, which is swell. The problem I
have is that I want to cache the components of the color as well (as
separate CGFloat properties), but I don't see where I can interpose
myself to calculate and cache this when the color is set (either at
run-time, or because it was calculated earlier and saved out to disk
as part of the document).
In other words, I read my document off of disk, and CoreData magically
makes sure that my "color" property is set. But since it never seems
to call my setColor: setter, I don't see it happen, which is when I
would like to go ahead and cache my separate red, green, and blue
properties. Since these are calculated from the color (which is
saved), there's no reason to ever store them to disk.
- (void)_cacheColor {
NSColor* rgb = [_color
colorUsingColorSpaceName:NSCalibratedRGBColorSpace];
CGFloat red, green, blue, alpha;
[rgb getRed:&red green:&green blue:&blue alpha:&alpha];
self.red = red;
self.green = green;
self.blue = blue;
}
- (void)setColor:(NSColor*)c {
[self willAccessValueForKey:@"color"];
if (c != _color) {
[self willChangeValueForKey:@"color"];
[_color release];
_color = [c copy];
[self didChangeValueForKey:@"color"];
[self _cacheColor];
}
[self didAccessValueForKey:@"color"];
}
I thought that perhaps if I just observed when the "color" property
changed, I could fire then:
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)image
change:(NSDictionary *)change context:(void *)context {
if ([keyPath isEqualToString:@"color"]) {
NSNumber* n = [change objectForKey:NSKeyValueChangeNewKey];
if ([n boolValue]) {
[self _cacheColor];
}
return ;
}
}
but that code never seems to fire either. sigh. Digging into the
documentation some more, it seemed that implementing this might do the
trick:
- (void)setPrimitiveValue:(id)value forKey:(NSString *)key {
if ([key isEqualToString:@"color"]) {
[self setColor:value];
return ;
}
[super setPrimitiveValue:value forKey:key];
}
But again, it never fires.
I'm assuming I'm missing something obvious...
Thanks.
--> Michael B. Johnson, PhD
--> http://homepage.mac.com/drwave (personal)
--> http://xenia.media.mit.edu/~wave (alum)
--> MPG Lead
--> Pixar Animation Studios
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden