观察属性或覆盖setter是否更好?

时间:2013-03-20 22:01:01

标签: ios objective-c cocoa-touch properties key-value-observing

假设我们有CustomButton接口:

@interface CustomButton : UIButton
    @property (nonatomic, assign) CGFloat minWidth;
@end

每次更改minWidth时,我们都希望再次布置CustomButton。据我所知,我们有两个解决方案:

观察财产的价值

// In -initWithFrame:
[self addObserver:self forKeyPath:@"minWidth" options:0 context:nil];

// In -observeValueForKeyPath:ofObject:change:context:
[self setNeedsLayout];

覆盖minWidth的二传手

// In -setMinWidth:
_minWidth = minWidth; // Side note: it's an ARC project
[self setNeedsLayout];

哪一个是正确的解决方案,为什么?

2 个答案:

答案 0 :(得分:5)

我可以想到三个理由来覆盖setter而不是KVO属性。

1:副作用可能会有所不同

除非您明确需要或想要副作用,否则最小阻力(或本例中的开销)的路径是覆盖设定者。 KVO不仅涉及对给定属性的绑定,还涉及观察者在绑定期间将处于活动状态的假设。甚至不要让我开始考虑KVO的调试挑战性!臭名昭着的“NSKVODeallocateBreak断点”足以吓跑任何人。

2:传统智慧

“观察自己”,虽然理论上是一个好主意,但要胜过正确而不是压倒二传手。 KVO在setter之上也是一个额外的(但是最小的)开销量,它只对绑定到其他对象非常有用。此外,如果你把一个类视为一个独立的单元,那么它真的不需要观察它自身的任何属性。 Setter精确存在,以便给定的类可以选择对其属性的变化做出反应,甚至拒绝或修改所述更改。

3:我们都很懒惰

通过观察自己,你现在已经致力于KVO的规则了:即记住要以观察者的身份移除自己,并实施

-observeValueForKeyPath:ofObject:change:context:

相对于手头的任务,这是 方式 过多的工作。你为什么要记得做所有这些?

答案 1 :(得分:0)

正确的答案实际上在你的问题中:

  

每次更改minWidth时,我们都想再次布局CustomButton。

编程中没有绝对的答案,这使它成为一门科学艺术。但是,您可以采用一些策略来确保编程行为不会妨碍您尝试实现或创建的内容。编程本身就是达到目的的手段。

因此,您的代码应该尽可能复杂,但不能再多了。

虽然您可以使用键值对观察,并且没有人会对您造成错误,但更好的方法(在您的问题的上下文中)将覆盖setter,因为这是您的意图(上面引用)它是最简单,最简洁和文字的形式。

在放大级别,您的代码应尽可能易于阅读和解析,以便将这些简单的块组合成更复杂的结构。如果在最大限度放大的细节代码是不必要的冗长或复杂,这将表现为整个项目的摩擦(更难调试,更容易出错,等等)。