为什么此代码不符合KVO标准?

时间:2012-01-12 03:58:48

标签: objective-c cocoa binding key-value-observing

我有一个NSViewController子类,带有一个方便的方法来像这样返回窗口控制器

@interface ILViewController : NSViewController

- (ILWindowController *)windowController;

@end

@implementation ILViewController

- (NSWindowController *)windowController {
    return self.view.window.windowController;
}

- (void)setView:(NSView *)view {
    [self willChangeValueForKey:@"windowController"];
    [super setView:view];
    [self didChangeValueForKey:@"windowController"];
}

@end

窗口控制器有一个名为NSString *的{​​{1}}属性,我试图通过视图控制器绑定它。但是,我在运行时收到此错误。

mainStatus

为什么会这样?我已适当发送了KVO通知。

以下代码使用了ivar并且实际上不符合KVO,结果不会导致任何错误....

Cannot update for observer <NSAutounbinderObservance 0x1005cf990> for the key path 
"windowController.mainStatus" from <ILViewController 0x1001976b0>, most likely because
the value for the key "windowController" has changed without an appropriate KVO
notification being sent. Check the KVO-compliance of the ILViewController class.

这让我感到困惑......有人能看出为什么第一个实现不符合KVO吗?

修改

知道了,如果在为ViewController设置视图后将视图添加到窗口,那么视图的窗口确实在没有适当的KVO通知的情况下被更改。但是,当我尝试观察视图窗口的窗口控制器时,我遇到了这样的错误

@interface ILViewController : NSViewController {
    ILWindowController *_windowController;
}

- (ILWindowController *)windowController;

@end

@implementation ILViewController

- (NSWindowController *)windowController {
    return _windowController;
}

- (void)setView:(NSView *)view {
    [super setView:view];
    _windowController = view.window.windowController;
}

@end

因此,如果您无法观察视图窗口,那么当视图窗口发生变化时,必须要有一些方法可以得到通知。有谁知道怎么做?

此外,这些仍然无法解释为什么使用没有KVO通知的iVar的第二版代码实际上有效。

2 个答案:

答案 0 :(得分:4)

如果您设置了视图,然后将视图添加到窗口,那么windowController将更改,而不会发送KVO通知。您需要观察自己的视图window,并在发生变化时发出意愿/更改通知(可能是自动密钥路径依赖的东西为您做了这个,我不记得它是否真的适用于路径或只是值)。同样,如果窗口的windowController发生变化,那么您将遇到同样的问题。

修改:此方法称为-automaticallyNotifiesObserversForKey:。我倾向于说它不支持关键路径,因此您必须自己进行手动观察/通知。

答案 1 :(得分:0)

  

KVO autonotifying仅支持-set:返回void的方法

未声明某些方法,您的编译器可能会考虑其返回ID并继续。