使用KVO的简单MVVM模式

3

我正在尝试使用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的获取和设置,但从未成功过。


你在代码中添加了textField.delegate = self吗? - Ahmad F
@Ahmad F - 是的,在Storyboard中。我在shouldChangeCharactersIn上设置了一些断点,代码就停在那里了。模型和视图模型中字符串的值已经正确更改。 - Pedro
1个回答

2

更新

根据苹果文档,在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方法,因为它获取的是更新之前的文本框值。此外,keyPath == "info"永远不会为真。难道不应该是其他东西吗?例如:keyPath == "viewModel.infoText"


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接