Re: Core Data Derived Values
Re: Core Data Derived Values
- Subject: Re: Core Data Derived Values
- From: Robert McNally <email@hidden>
- Date: Fri, 8 Jul 2005 13:31:38 -0700
>Hi,
>
>I'm trying to implement derived values with Core Data. I want to use it to display an individual's full name by combining several other fields ("firstName", "lastName", etc.). In fact, what I'm trying to do is exactly what the ADC article, "NSPersistentDocument Core Data Tutorial" describes on the "Support for the Derived Value" page. However, there's a problem with this for me. I'm using a relationship to store the name information, and when the values change, I don't get notified. Using the "setKeys:triggerChange..." method works great when "keys" are attributes, but it (apparently) doesn't work for keys that belong to relationships. Here's an example of what I'd like to do, but what doesn't seem to work:
>
>+ (void)initialize
>{
> NSArray *keys = [NSArray arrayWithObject:@"fullName"]; // (fullName is a relationship)
> [self setKeys:keys triggerChangeNotificationsForDependentKey:@"displayName"];
>}
>
>Anyone have any suggestions?
>
>Thanks,
>Todd
The only way I have found to do what you're talking about is to have the object in question observe notifications of changes in the NSManagedObjectContext and look for changes (updates, insertions, deletions) of the objects it's dependent upon through relationships. Something like this is used the CoreRecipes examples I believe. Here is the pattern adapted to your case:
- (void)commonAwake {
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:@selector(refresh:)
name:NSManagedObjectContextObjectsDidChangeNotification
object:[self managedObjectContext]];
}
- (void)awakeFromInsert {
[super awakeFromInsert];
[self commonAwake];
}
- (void)awakeFromFetch {
[super awakeFromFetch];
[self commonAwake];
}
- (void)didTurnIntoFault {
[[NSNotificationCenter defaultCenter] removeObserver:self];
[super didTurnIntoFault];
}
- (void)refresh
{
[self willChangeValueForKey:@"displayName"];
[displayName release]; displayName = nil;
[self didChangeValueForKey:@"displayName"];
}
- (void)refresh:(NSNotification *)notification
{
NSEnumerator *enumerator;
id object;
BOOL refresh = NO;
NSSet *updated = [[notification userInfo] objectForKey:NSUpdatedObjectsKey];
NSSet *inserted = [[notification userInfo] objectForKey:NSInsertedObjectsKey];
NSSet *deleted = [[notification userInfo] objectForKey:NSDeletedObjectsKey];
NSManagedObject* fullNameObject = [self fullNameObject];
enumerator = [updated objectEnumerator];
while ((refresh == NO) && (object = [enumerator nextObject])) {
if (object == fullNameObject) {
refresh = YES;
}
}
enumerator = [inserted objectEnumerator];
while ((refresh == NO) && (object = [enumerator nextObject])) {
if (object == fullNameObject) {
refresh = YES;
}
}
enumerator = [deleted objectEnumerator];
while ((refresh == NO) && (object = [enumerator nextObject])) {
if (object == fullNameObject) {
refresh = YES;
}
}
//
// This is in the CoreRecipes example but I'd like to know why?
//
if ( (refresh == NO) && (([updated count] == 0) && ([inserted count] == 0) && ([deleted count]==0))) {
refresh = YES;
}
if (refresh) {
[self refresh];
}
}
- (NSString*)displayName
{
if(displayName == nil) {
NSManagedObject* fullNameObject = [self fullNameObject];
NSString* firstName = [fullNameObject valueForKey:@"firstName"];
NSString* lastName = [fullNameObject valueForKey:@"lastName"];
displayName = [[NSString stringWithFormat:@"%@ %@", firstName, lastName] retain];
}
return displayName;
}
- (void)setDisplayName:(NSString*)s
{
// noop
}
--
______________________________________________________________________
Robert McNally, Arciem Engineering <http://www.arciem.com>
626/963-7760
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Cocoa-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden