Swift MVC:让 viewController 观察模型 属性,在 属性 变化时更新视图

Swift MVC: Having viewController observe Model property, updating the view when the property changes

我的模型的主要 class 是浓度 属性 称为 flipCount

class Concentration {
    @objc var flipCount = 0

在我的 ViewController 中,我有一个 @IBOutlet 到一个名为 flipCountLabel 的 UILabel

class ViewController: UIViewController {
    lazy var game = Concentration(numberOfPairsOfCards: self.cardButtons.count / 2)
    @IBOutlet weak var flipCountLabel: UILabel!
...

我想在 flipCount 更改时更新 flipCountLabel 中的文本。我试图通过在我的 ViewController 的 viewDidLoad 方法中调用 UIViewController 的观察方法来做到这一点。有几种观察方法。我不知道哪一个是正确的,也找不到一个例子来说明如何用什么填充变量。

我试过用self.observe喜欢

    self.observe(KeyPath<Concentration,Int>(game, "flipCount"), changeHandler: {
        self.flipCountLabel.text = "Flip Count: \(flipCount)"
    })

每次 game.flipCount 更新时,我都会尝试更新 ViewControllers flipCountLabel.text。 我觉得这是kvo?

observe 方法是实现此目的的方法,只要对您的代码进行一些更改即可。

将您的 Concentration class 更改为以下内容:

class Concentration: NSObject {
    @objc dynamic var flipCount = 0
}

为了让 KVO 在 Swift 中工作,属性需要同时标记 @objcdynamic。 class 需要继承自 NSObject 以防止运行时错误。

您的 ViewController class 应如下所示:

class ViewController: UIViewController {
    @objc lazy var game = Concentration()
    @IBOutlet weak var flipCountLabel: UILabel!

    private var observation: NSKeyValueObservation?

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)

        self.observation = self.observe(\.game.flipCount) { _, _ in
            self.flipCountLabel.text = "\(self.game.flipCount)"
        }
    }

    override func viewDidDisappear(_ animated: Bool) {
        super.viewDidDisappear(animated)

        self.observation = nil
    }
}

game 属性 需要标记为 @objc (再次防止运行时错误)。此外,observe 方法的 documentation 声明

when the returned NSKeyValueObservation is deinited or invalidated, it will stop observing

这就是为什么您需要对 observe 方法返回的值保持强引用。

此外,请考虑使用我在此处使用的 KeyPath 表示法。如果你打错了,它会在编译时失败,而不是在运行时。

希望对您有所帮助!