实现自己的setter还是使用KVO?
简而言之,当属性值发生变化时,我必须更新代码中的一些逻辑,例如:
- (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 实现更聪明,因此我会不要破坏东西。
In short, when the property value changing, I have to update some logic in my code, for example:
- (void)setProp:(NSString *)theProp
{
if (prop != theProp){
[prop release];
prop = [theProp copy];
[self myLogic];
}
}
or:
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context
{
if ([keyPath isEqualToString:@"prop"]){
[self myLogic];
}
}
Which is the best way, and WHY?
EDIT: I prefect the second way, because I don't know what the compiler will generate @synthesize
directive for me, I choose to believe the compiler is more smarter than my owe setter implementation, hence I will not break something.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
如果您对同一对象的更改感兴趣,则可以使用第一个片段。仅当您对其他对象的更改感兴趣时才需要使用第二个,用它来观察 self 是多余的。
The first snippet is the way to go, if you’re interested in changes in the same object. You only need to use the second if you are interested in changes to other objects, using it to observe
self
is overkill.艰难的决定,恕我直言,这两种选择都很糟糕。
第一个强制您编写自己的 setter,这是很多样板代码。
(更不用说,如果您希望相关属性的 KVO 正常工作,您还必须记住使用willChangeValueForKey:
和didChangeValueForKey:
触发 KVO 通知。)第二个选项也相当重量级,您的实现还不够。如果你的超类也有一些 KVO 怎么办?您必须在处理程序中的某个位置调用
super
。如果没有,你确定你的超类不会改变吗? (有关 KVO 的更多信息,请参见相关问题。)有时,您可以使用绑定等其他方法来回避问题(如果您使用的是Mac)或普通通知(您可以发布模型更改的通知,所有感兴趣的各方都应该刷新)。
如果您有很多像这样的重新计算并且找不到任何更好的方法,我会尝试编写一个具有更好的观察支持的超类,其界面如下:
这将需要更多的工作,但它将使您的类干净地分开,并且您可以在一处解决所有与KVO相关的问题。如果没有足够的重新计算属性来使其有价值,我通常会使用第一个解决方案(自定义设置器)。
Tough call, IMHO both options suck.
The first one forces you to write your own setter, which is a lot of boilerplate code.
(Not to mention that you have to remember to also fire KVO notifications withwillChangeValueForKey:
anddidChangeValueForKey:
if you want KVO for the property in question to work.)The second option is also quite heavy-weight and your implementation is not enough. What if your superclass also has some KVO in place? You’d have to call
super
somewhere in the handler. If not, are you sure your superclass won’t change? (More about KVO in a related question.)Sometimes you can sidestep the issue using other methods like bindings (if you’re on a Mac) or plain notifications (you can post a notification that a model changed and all interested parties should refresh).
If you have many recalculations like this and can’t find any better way around, I would try to write a superclass with better observing support, with interface like this:
This will take more work, but it will keep your classes cleanly separated and you can solve all KVO-related problems on one place. If there are not enough recalculated properties to make this worthwile, I usually go with the first solution (custom setter).
在您的情况下,最好的选择是在设置器内添加逻辑。如果您的属性声明类似于
@property (nonatomic, copy) YCYourClass *prop;,
则您的 setter 实现是正确的。 KVO 通常在检查外部对象属性的更改时使用。
NSNotifications 更适合通知事件。
In your case the best option is to add the logic inside the setter. Your setter implementation is correct if your property declaration is something like
@property (nonatomic, copy) YCYourClass *prop;
KVO is used normally when checking for changes on external objects properties.
NSNotifications are better suited to inform of events.