Making KVO safer

One of the main issues with KVO is caused by classes not knowing what observers a superclass has registered.
When a subclass also wants to observe the same keyPath they have the danger of removing the observer from the super class.

- (void)someMethod
{
    [self addObserver:self
           forKeyPath:@"view.frame"
              options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionInitial
              context:NULL];
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    if ([keyPath isEqualToString:@"view.frame"])
    {
        [self viewDidChangeFrame];
    }
    else
    {
        [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
    }
}

- (void)removeKVO
{
    [self removeObserver:self forKeyPath:@"view.frame"];
}

When super also expects to receive callbacks for view.frame expected behaviour will quickly break and be hard to track down.

To protect against this the context can be used to distinguish between different classes:

static void *HCViewControllerKVOContext = &HCViewControllerKVOContext;
- (void)someMethod
{
    [self addObserver:self
           forKeyPath:@"view.frame"
              options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionInitial
              context:HCViewControllerKVOContext];
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    if (context == HCViewControllerKVOContext)
    {
        if ([keyPath isEqualToString:@"view.frame"])
        {
            [self viewDidChangeFrame];
        }
    }
    else
    {
        [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
    }
}

- (void)remoevKVO
{
    [self removeObserver:self forKeyPath:@"view.frame" context:HCViewControllerKVOContext];
}

This will also eliminate calling -[super observeValueForKeyPath:ofObject:change:context:] when the super class doesn't expect it, which will crash.

comments powered by Disqus