Search code examples
cocoacompiler-warningskey-value-observing

Warning: MyClass:NSObject does not implement key value observing? How can that be?


I just recently resumed work on a Cocoa project that I left a few months ago. Cocoa is a strange beast if you have not been using it for a while.

Anyway, at some point the compiler started dropping warnings:

Incomplete implementation of class 'MyClass'
Method definition for '-addObserver:forKeyPath:options:context' not found
Method definition for '-removeObserver:forKeyPath:' not found
Class 'MyClass' does not fully implement the 'MyZoomScrollViewDataSource' protocol

But MyClass is derived from NSObject, which does in fact implement -addObserver:forKeyPath: and -removeObserver:forKeyPath:context:.

The protocol looks like this:

@protocol MyZoomScrollViewDataSource
    // The range of Data that should be shown. This corresponds to the horizontal  
    //   zoom and the scroll value of self.
    @property FRange selectionRange;

    // Also, make sure the dataSource is KVO compliant
    - (void)addObserver:(NSObject *)anObserver forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context;
    - (void)removeObserver:(NSObject *)anObserver forKeyPath:(NSString *)keyPath;
@end

The class looks like this:

@interface MyClass : NSObject <MyZoomScrollViewDataSource> {
    IBOutlet Outlets...
    variables...
}
@properties...
(IBAction)actions...
- methods...
@end

I guess my Cocoa skills are in deep need for a refresh. But still, these methods should be inherited from NSObject, so how can MyClass not implement these methods?


Solution

  • One possible solution to this is to explicitly add those functions to the class. This seems rather hackish to me. I would gladly use a cleaner way to do this if there is one.

    @implementation MyClass
    
    - (void)addObserver:(NSObject *)anObserver forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context {
        [super addObserver:anObserver forKeyPath:keyPath options:options context:context];
    }
    
    - (void)removeObserver:(NSObject *)anObserver forKeyPath:(NSString *)keyPath {
        [super removeObserver:anObserver forKeyPath:keyPath];
    }
    
    @end
    

    The strangest thing is: This works not only with super, it works with self, too! Consider my mind blown. What the heck?