2016-10-02 42 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中賦值是正常的,並且不會觸發無限遞歸。

相關問題