簡體   English   中英

獲取聲明為協議的屬性時didSet調用

[英]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()didSetviewModel

如果直接將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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM