![](/img/trans.png)
[英]Why is 'didset' called on a property when I set the property of that property?
[英]didSet called when getting a property declared as a protocol
這是一些代碼:
import UIKit
protocol ViewModelProtocol {
var price: String { get }
}
class ViewModel: ViewModelProtocol {
var price: String {
return "$420"
}
}
class ViewController: UIViewController {
// If you change the type to ViewModel directly, no infinite loop
var viewModel: ViewModelProtocol? = nil {
didSet {
print("viewModel didSet called")
updateDisplay()
}
}
required init?(coder aDecoder: NSCoder) {
viewModel = ViewModel()
super.init(coder: aDecoder)
updateDisplay()
}
func updateDisplay() {
print("In updateDisplay()")
print("\(viewModel?.price)")
// if you access the viewModel like this, no infinite loop
// if let v = viewModel {
// print("\(v.price)")
// }
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
此代碼將在無限循環中運行。 具體來說,它在updateDisplay()
print("\\(viewModel?.price)")
updateDisplay()
和didSet
的viewModel
。
如果直接將viewModel
的類型更改為ViewModel
(跳過協議),則無限循環消失。 或者,如果在使用updateDisplay()
之前解開viewModel
,則無限循環也會消失。
這是在Swift 2中,雖然我還沒有驗證它是否在早期的Swift中具有相同的行為。 另一個數據點,調用協議上的方法不會導致調用didSet
。
這看起來像是一個Swift bug嗎?
這是一個非常令人印象深刻的案例。
你的willSet屬性可能是一個問題,你的協議類型里面有一個readonly屬性。 我做了很多測試,很難找到解決方案。 但是,如果你真的需要繼續這樣做......我認為以下改變可以幫助你
protocol ViewModelProtocol {
var price: String { get set }
}
class ViewModel: ViewModelProtocol {
var price: String {
get {
return "$420"
}
set {
return
}
}
//...
}
如你所說......只有在嘗試通過viewModel對象直接訪問price屬性時才會出現問題
我只是把我的答案放在這里,因為它不適合評論字段大小。
但是非常令人印象深刻......我會盡力找到最終解決方案。 :)
似乎不僅我有didSet {}的這個問題。 這個問題有一個開放的雷達: https : //openradar.appspot.com/22574299
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.