Skip navigation.
 
mlRe: CoreData undo and observing related objects
FROM : Martin Wennerberg
DATE : Mon Nov 20 12:05:40 2006

There was another error in my code that made the observation fail. So 
observing self actually works fine, as expected.

For completeness, here's a short example program of how to update 
observation of related core data objects.

In this example a Parent object has a relation to a Child. When the 
child's value changes the parent updates it's own value to the same. 
(In a real world it would have to do something more interesting with 
it, or else it would be better to simply access the child value via 
the parent.)

Here's the complete code for the Parent class:

@interface Parent :  NSManagedObject
{
   BOOL    isObseringSelf;
}
@end

@implementation Parent
- (void) startObservingMyChildProperty
{
    [self addObserver:self forKeyPath:@"child" options:
(NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld) 
context:NULL];

    Child  *child = [self valueForKey:@"child"];
    if (child)
    {
        [self setValue:[child valueForKey:@"value"] forKey:@"value"];
        [child addObserver:self forKeyPath:@"value" options:0 
context:NULL];
    }
    isObservingSelf = YES;
}

- (void) stopObservingMyChildProperty
{
    if (isObservingSelf)
    {
        [self removeObserver:self forKeyPath:@"child"];

        Child  *child = [self valueForKey:@"child"];
        if (child)
            [child removeObserver:self forKeyPath:@"value"];

        isObservingSelf = NO;
    }
}

- (void) dealloc
{
    [self stopObservingMyChildProperty];
    [super dealloc];
}

- (void)didTurnIntoFault
{
    [self stopObservingMyChildProperty];
    [super didTurnIntoFault];
}

- (void) awakeFromInsert
{
    [super awakeFromInsert];
    [self startObservingMyChildProperty];
}

- (void) awakeFromFetch
{
    [super awakeFromFetch];
    [self startObservingMyChildProperty];
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)
object change:(NSDictionary *)change context:(void *)context
{
    if ([object isEqual:[self valueForKey:@"child"]])
        [self setValue:[object valueForKey:@"value"] forKey:@"value"];
    else if (object == self)
    {
        Child  *oldChild = [change 
objectForKey:NSKeyValueChangeOldKey];
        Child  *newChild = [change 
objectForKey:NSKeyValueChangeNewKey];

        if (oldChild && ![oldChild isEqual:[NSNull null]])
            [oldChild removeObserver:self forKeyPath:@"value"];
        if (newChild && ![newChild isEqual:[NSNull null]])
        {
            [newChild addObserver:self forKeyPath:@"value" options:0 
context:NULL];
            [self setValue:[newChild valueForKey:@"value"] 
forKey:@"value"];
        }
    }
    else
        NSLog (@"Unexpected %@", NSStringFromSelector(_cmd));
}
@end

Cheers,
   Martin Wennerberg

Related mailsAuthorDate
mlCoreData undo and observing related objects Martin Wennerberg Nov 17, 13:11
mlRe: CoreData undo and observing related objects Martin Wennerberg Nov 20, 12:05