2016-10-02 45 views
8

我测试了这个,看起来如果你改变didSet的值,你不会再打didSet在Swift中,是否重置didSet中的属性触发另一个didSet?

var x: Int = 0 { 
    didSet { 
     if x == 9 { x = 10 } 
    } 
} 

我可以依靠这个吗?它是否记录在某处?我没有在Swift Programming Language文档中看到它。

+0

刚刚在Xcode 8 Playground(Swift 3)上测试过并获得了相同的结果。如果您将属性从'didSet'更改,则'didSet'将再次调用__not__。 –

+0

“我能依靠这个吗”是的。 – matt

+0

我实际上在我的数组上有'didSet',最后还有一个'defer'用于弹出* last *元素。猜猜发生了什么?它崩溃了,因为我弹出了每一个让我的数组变空的元素,必须在'defer'内部做一个'if else',所以如果'myArray.isEmpty!= true'我不会弹出。 – Honey

回答

10

我也想过,这是不可能的(也许它不是在Swift 2中),但我测试了它,发现苹果使用这个的地方是an example。 (在“查询和设置类型属性”)

struct AudioChannel { 
    static let thresholdLevel = 10 
    static var maxInputLevelForAllChannels = 0 
    var currentLevel: Int = 0 { 
     didSet { 
      if currentLevel > AudioChannel.thresholdLevel { 
       // cap the new audio level to the threshold level 
       currentLevel = AudioChannel.thresholdLevel 
      } 
      if currentLevel > AudioChannel.maxInputLevelForAllChannels { 
       // store this as the new overall maximum input level 
       AudioChannel.maxInputLevelForAllChannels = currentLevel 
      } 
     } 
    } 
} 

而且这段代码的下方,有以下注意事项:

在第一这两个检查中,didSet观测台currentLevel到一个不同的价值。 这不是,但是,导致观察员再次被调用

+0

这不再适用于Swift 4,并且会导致我刚在Swift 4中测试的循环 – thedeveloper3124

+3

@developer3124,它仍然有效。 – thislooksfun

1

它会工作得很好,但从您的API使用者的角度来看,它似乎非常糟糕。

它没有递归,我怀疑它可能的方式,所以这至少是好的。

我可以想到一些情况,在这种情况下,二传手可以改变我设定的设置。一个这样的例子可能是一个设置为一个角度的变量,该变量被自动标准化为[0, 2π]

+0

在Swift 3上做了这个改变吗?我记得在Swift 2中递归调用实际上已经到位。 –

+0

在我的情况下,我四舍五入到最近的一些其他值。如果他们没有设置预先取得的值,它似乎不值得让应用程序崩溃。 –

0

From Apple docs(重点煤矿):

同样,如果您实现didSet观察者,它通过包含旧属性值恒定 参数。您可以命名 参数或使用oldValue的默认参数名称。 如果您将 赋值给其自己的didSet观察器中的属性,则您分配的新值 将替换刚刚设置的值

因此,在didSet中赋值是正常的,并且不会触发无限递归。

相关问题