DidSet called when a property declared as a protocol is received

Here is the code:

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.
    }
}

This code will run in an infinite loop. In particular, it bounces between print("\(viewModel?.price)")in updateDisplay()and didSetfor viewModel.

If you change the type viewModelto viewModeldirectly (skipping the protocol), the infinite loop disappears. Alternatively, if you expand viewModelin updateDisplay()before using it, an endless loop will also disappear.

This is in Swift 2, although I have not tested to see if it has the same behavior in earlier Swift. Another data point that invokes methods in the protocol does not invoke a call didSet.

Does this sound like a Swift bug for you?

+4
2
+2

.

willSet , readonly. , . , ... ,

protocol ViewModelProtocol {
    var price: String { get set }
}

class ViewModel: ViewModelProtocol {
    var price: String  {
        get {
            return "$420"
        }

        set {
            return 
        }
    }
    //...
}

... viewModel

, .

... .:)

+2

Source: https://habr.com/ru/post/1608386/


All Articles