【问题标题】:Is it better to observe properties or override setters?观察属性或覆盖设置器更好吗?
【发布时间】:2013-03-20 22:01:01
【问题描述】:

假设我们有这个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];

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

【问题讨论】:

  • This 可能会有所帮助。

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


【解决方案1】:

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

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

除非您明确需要或想要副作用,否则阻力最小的路径(或本例中的开销)是覆盖 setter。 KVO 不仅涉及到给定属性的绑定,还涉及观察者在整个绑定期间都处于活动状态的假设。甚至不要让我开始谈论 KVO 的调试难度有多大!臭名昭著的“NSKVODeallocateBreak 上的断点”足以吓跑任何人。

2:传统智慧

“观察自己”虽然在理论上是个好主意,但比重写 setter 更难。 KVO 也是设置器之上的额外(但最小)开销,仅对绑定到其他对象真正有用。此外,如果您将一个类视为一个自包含的单元,那么它确实不需要观察其自身的任何属性。 Setter 精确地存在,因此给定的类可以选择对其属性的更改做出反应,甚至拒绝或修改所述更改。

3:我们都很懒

通过观察自己,您现在已经遵守了 KVO 的规则:即记住将自己移除为观察者,并实施

-observeValueForKeyPath:ofObject:change:context:.

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

【讨论】:

  • 覆盖设置器通过不发送正确的事件来破坏 KVO(除非您手动实现)。只是一个旁注。
  • @LoïsDiQual 我想我们会选择一个非此即彼的情况,在这里。如果你想两者兼得,请成为我的客人。
  • 我不是在谈论观察self,而是从应用程序的其他地方观察CustomButton 的实例。
  • @LoïsDiQual 覆盖设置器不会破坏 KVO,除非它用于 NSManagedObject
【解决方案2】:

正确答案其实就在你的问题里:

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

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

因此,您的代码应该尽可能复杂,但仅此而已。

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-07-28
    • 2015-03-13
    • 2017-08-29
    • 2015-11-01
    • 1970-01-01
    • 2014-03-11
    • 1970-01-01
    相关资源
    最近更新 更多