这是一些代码:
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)")
和 viewModel 的
。didSet
之间跳动
如果直接将 viewModel
的类型更改为 ViewModel
(跳过协议(protocol)),无限循环就会消失。或者,如果您在使用 updateDisplay()
之前打开 viewModel
,无限循环也会消失。
这是在 Swift 2 中的,尽管我还没有验证它在早期的 Swift 中是否有相同的行为。另一个数据点,调用协议(protocol)上的方法不会导致调用 didSet
。
你觉得这像是 Swift 的 bug 吗?
最佳答案
看来不止我有didSet{}这个问题。 此问题有公开雷达:https://openradar.appspot.com/22574299
关于swift - 获取声明为协议(protocol)的属性时调用 didSet,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32705627/