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 中工作,属性需要同时标记 @objc
和 dynamic
。 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 表示法。如果你打错了,它会在编译时失败,而不是在运行时。
希望对您有所帮助!
我的模型的主要 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 中工作,属性需要同时标记 @objc
和 dynamic
。 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 表示法。如果你打错了,它会在编译时失败,而不是在运行时。
希望对您有所帮助!