我有一个NSTreeController
子类。它有一个名为selectedProject
的属性,它是自定义的,并在标题中声明如下:
@property (nonatomic, readonly) LPProject *selectedProject;
在私人实施中就像这样:
@property (nonatomic, readwrite, assign) LPProject *selectedProject;
重要的是,在我修改TreeController中的selectedProject
的每一点上,我都会查看生成的setter / getters。我从不直接修改iVar。
基本上,此属性存在的原因是因为selectedObjects
的正常selection
和NSTreeController
属性未被输入,因为我知道此TreeController将始终只管理LPProject对象并且一次只能选择一个项目,我想要一个漂亮干净的iVar来使用,而不是经常获取selectedObjects,检查是否有一个,获取数组中的第一个对象,等等。
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
的关键路径应该有效。
任何人都可以对此有所了解吗?我错过了什么?
答案 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通知,并使用最少的粘合代码。