简而言之,当属性值发生变化时,我必须更新代码中的一些逻辑,例如:
- (void)setProp:(NSString *)theProp
{
if (prop != theProp){
[prop release];
prop = [theProp copy];
[self myLogic];
}
}
或:
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context
{
if ([keyPath isEqualToString:@"prop"]){
[self myLogic];
}
}
哪种方法最好,为什么?
编辑:我完全采用第二种方式,因为我不知道编译器会为我生成@synthesize
指令,我选择相信编译器比我的setter实现更聪明,因此我不会打破了一些东西。
答案 0 :(得分:5)
如果您对同一对象的更改感兴趣,那么第一个片段就是您的选择。如果您对其他对象的更改感兴趣,则只需使用第二个,使用它来观察self
是否过度。
答案 1 :(得分:3)
艰难的电话,恕我直言两种选择都很糟糕。
第一个强迫你编写自己的setter,这是很多样板代码。 (更不用说如果你想让相关财产的KVO工作,你必须记得用 willChangeValueForKey:
和didChangeValueForKey:
发送KVO通知。)
第二个选项也很重,你的实现还不够。如果您的超类也有一些KVO怎么办?你必须在处理程序的某个地方调用super
。如果没有,你确定你的超类不会改变吗? (更多关于related question中的KVO。)
有时你可以使用其他方法来回避问题,比如绑定(如果你在Mac上)或普通通知(你可以发布模型改变的通知,所有感兴趣的人都应该刷新)。
如果你有很多这样的重新计算并且找不到更好的方法,我会尝试编写一个具有更好观察支持的超类,其界面如下:
[self addTriggerForKeyPath:@"foo" action:^{
NSLog(@"Foo changed.");
}];
这将需要更多工作,但它会使您的课程保持清晰分离,您可以在一个地方解决所有与KVO相关的问题。如果没有足够的重新计算属性来实现这个价值,我通常会选择第一个解决方案(自定义设置器)。
答案 2 :(得分:0)
在您的情况下,最好的选择是在setter中添加逻辑。如果您的属性声明类似于
,那么您的setter实现是正确的@property(非原子,复制)YCYourClass * prop;
在检查外部对象属性的更改时,通常会使用KVO。
NSNotifications更适合告知事件。