带KVO的简单MVVM

时间:2017-06-28 13:05:31

标签: swift mvvm key-value-observing

我正在尝试使用kvo创建一个简单的mvvm模型

我的目标是当UITextField文本发生变化时,自动更改UILabel文本。 但由于某种原因,observeValue函数未被调用

import UIKit
class ViewController: UIViewController, UITextFieldDelegate {

    var viewModel : TestViewModel?
    @IBOutlet weak var LBLABEL: UILabel!

    override func viewDidLoad() {
        super.viewDidLoad()
        viewModel = TestViewModel()

        addObserver(self, forKeyPath: #keyPath(viewModel.infoText), options:  [.old, .new], context: nil)

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

    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        viewModel?.infoText = textField.text
        return true
    }


    // MARK: - Key-Value Observing
    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        if keyPath == "info" {
            // Update Time Label
            LBLABEL.text = viewModel?.infoText
        }
    }

}


class TestViewModel : NSObject{
    var model : TestModel

    var infoText:String? {
        didSet{
            model.info = self.infoText

        }
    }

    override init() {
        model = TestModel()
    }
}


class TestModel {
    var info:String?
}

我已经尝试更改观察者的声明,甚至ViewModel获取并设置并且从未成功

1 个答案:

答案 0 :(得分:1)

<强>更新

根据Apple文档,在Swift 4中创建关键路径的观察者会更加简单。

class MyObserver: NSObject {
    @objc var objectToObserve: MyObjectToObserve
    var observation: NSKeyValueObservation?

    init(object: MyObjectToObserve) {
        objectToObserve = object
        super.init()

        observation = observe(\.objectToObserve.myDate) { object, change in
            print("Observed a change to \(object.objectToObserve).myDate, updated to: \(object.objectToObserve.myDate)")
        }
    }
}

let observed = MyObjectToObserve()
let observer = MyObserver(object: observed)

observed.updateDate()

您需要将dynamic添加到要观察的NSObject子类的属性中。在你的情况下:

@objc dynamic var infoText:String? {
    didSet{
        model.info = self.infoText            
    }
}

顺便说一下,我不知道为什么你想要textField:shouldChangeCharactersIn,因为它在更新之前得到了textfield值。此外,keyPath == "info"永远不会成真。不应该是别的东西。例如,keyPath == "viewModel.infoText"