NSTreeController:自定义属性keypath的KVO失败。

时间:2016-01-26 03:58:08

标签: objective-c macos cocoa key-value-observing nstreecontroller

设置

我有一个NSTreeController子类。它有一个名为selectedProject的属性,它是自定义的,并在标题中声明如下:

@property (nonatomic, readonly) LPProject *selectedProject;

在私人实施中就像这样:

@property (nonatomic, readwrite, assign) LPProject *selectedProject;

重要的是,在我修改TreeController中的selectedProject的每一点上,我都会查看生成的setter / getters。我从不直接修改iVar。

基本上,此属性存在的原因是因为selectedObjects的正常selectionNSTreeController属性未被输入,因为我知道此TreeController将始终只管理LPProject对象并且一次只能选择一个项目,我想要一个漂亮干净的iVar来使用,而不是经常获取selectedObjects,检查是否有一个,获取数组中的第一个对象,等等。

LPProject

LPProject是Core Data的自定义NSManagedObject子类。它有一个名为enabled的属性。此属性是BOOL,由NSNumber表示。它的getter / setter由Xcode生成。

问题

在多个控制器中,我尝试查看enabled对象的selectedProject属性,如下所示:

[_myTreeController addObserver:self 
                    forKeyPath:@"selectedProject.enabled" 
                       options:0 
                       context:NULL];

我已经确认,当selectedProject发生更改时,KVO通知就会到达(因此,selectedProject.enabled会发生变化)。但是,当 enabled的{​​{1}}属性发生更改时(即所选项目本身保持不变),KVO通知才会到达。

然而,如果我改为订阅:

selectedProject

完美无缺。当[_myTreeController addObserver:self forKeyPath:@"selection.enabled" options:0 context:NULL]; 更改且enabled保持不变时,KVO通知即会到达。

我对此感到困惑,因为selectedProject符合KVO,我觉得selectedProject的关键路径应该有效。

任何人都可以对此有所了解吗?我错过了什么?

1 个答案:

答案 0 :(得分:1)

我不知道您如何以及何时更新selectedProject属性,但是由于基于selection的方法按预期工作(并且不仅仅是为此),我建议您制作来自selectedProject的{​​{1}}派生属性(selectedObjects为代理,而selection也是KVO):

selectedObjects

header属性声明保持不变,如果提供setter,则不需要实现声明。

这样做的好处是,当// tell Cocoa which property changes directly affect selectedProject + (NSSet*)keyPathsForValuesAffectingSelectedProject { return [NSSet setWithObject:@"selectedObjects"]; } - (LPProject*)selectedProject { // you might need to do some isKindOfClass checks if not all nodes are LPProject return self.selectedObjects.first; } 更改时,运行时将自动发送selectedProject属性的KVO通知,并使用最少的粘合代码。