【问题标题】:Swift MVC: Having viewController observe Model property, updating the view when the property changesSwift MVC:让 viewController 观察模型属性,在属性更改时更新视图
【发布时间】:2020-02-19 03:08:27
【问题描述】:

我的模型的主要类是 Concentration,带有一个名为 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?

【问题讨论】:

  • @Don 我无法在 Concentration 类中访问 FlipCountLabel。 IBOutlet 在 ViewController 中
  • 哦,对不起。没有仔细阅读。

标签: ios swift model-view-controller key-value-observing


【解决方案1】:

observe 方法是这里的方法,无论是对您的代码进行一些更改。

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

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

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

您的 ViewController 类应该如下所示:

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 状态

当返回的 NSKeyValueObservation 被取消初始化或无效时,它 将停止观察

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

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

希望对你有所帮助!

【讨论】:

  • 当我将@Objc 放在lazy var game = Concentration 前面时,我收到Property cannot be marked @objc because its type cannot be represented in Objective-C
  • 这就是为什么你需要让Concentration成为NSObject的子类
猜你喜欢
  • 2014-11-02
  • 2016-05-08
  • 2014-03-12
  • 2021-06-04
  • 2014-01-12
  • 1970-01-01
  • 1970-01-01
  • 2017-10-16
  • 1970-01-01
相关资源
最近更新 更多