我的iOS应用程序的UI非常复杂,以至于我有时会在启用/禁用/隐藏/显示某些按钮或视图时感到困惑。经过思考,我觉得这个app只有三个状态:空转、录音和播放。
因此,我创建了枚举类型AppState
的计算属性变量,我希望通过它观察状态变化,以便相应地更新UI。UI的一些变化包括显示或禁用按钮,以及从其父视图中删除自定义UIView
对象。
var curState : AppState = .Idling {
didSet {
if newValue != oldValue {
updateUI() // ?? better here?
}
}
willSet(newValue) {
updateUI() // ?? good here?
}
set {
updateUI() // ?? good here
}
}
我一直在使用上面的set
来调用updateUI()
方法,它工作得很好,但我想知道三个观察者中哪一个更好?我没有尝试过willSet
或didSet
,但我倾向于使用didSet
,因为我可以在更新UI之前比较oldValue
和newValue
。我可能错了,我洗耳恭听你的建议。
谢谢!
属性有两种类型:
- 存储属性,它有一个合成的后台实例变量,和一个隐式的
get
和set
定义,你不能覆盖。如果你想知道什么时候发生了变化,你可以使用willSet
和didSet
。 - 计算属性,它没有后备存储,需要显式的
get
和可选的set
。如果您想要更改通知,set
是这样做的地方。
不能混用和匹配,即存储属性不能有get
或set declaration, and computed properties can't have a
willSet or
didSet '声明。
在您的示例中,看起来您的appState
是一个存储变量。因此,实际上,放置观察者逻辑的正确位置是在willSet
或didSet
中。这里有权衡:
- 使用
willSet
,您的newValue
必须手动传递给任何功能需要它。 - 使用
didSet
,您的新值是存储属性本身的值,所有方法都可以通过self
访问它,因此不需要手动传递它。然而,这样做的代价是暂时使对象状态不一致(因为已经设置了一个值,但它的更新效果尚未发生),这可能导致需要注意的微妙状态错误。