The main class of my model is Concentration with a property called flipCount
class Concentration {
@objc var flipCount = 0
In My ViewController I have an @IBOutlet to a UILabel called flipCountLabel
class ViewController: UIViewController {
lazy var game = Concentration(numberOfPairsOfCards: self.cardButtons.count / 2)
@IBOutlet weak var flipCountLabel: UILabel!
...
I want to update the text in flipCountLabel when flipCount changes. I am trying to do this by placing a call to the observe method of UIViewController in my ViewController's viewDidLoad method. There are a few observe methods. I don't know which one is right and cannot find an example for how to what to fill in the variables with.
I have tried to use self.observe like
self.observe(KeyPath<Concentration,Int>(game, "flipCount"), changeHandler: {
self.flipCountLabel.text = "Flip Count: \(flipCount)"
})
I am trying to update the ViewControllers flipCountLabel.text every time game.flipCount is updated. I think this is kvo?
The observe
method is the way to go here, be it with some changes to your code.
Change your Concentration
class to the following:
class Concentration: NSObject {
@objc dynamic var flipCount = 0
}
In order for KVO to work in Swift, properties need to be marked with both @objc
and dynamic
. The class needs to inherit from NSObject
to prevent runtime errors.
Your ViewController
class should look something like this:
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
}
}
The game
property needs to be marked @objc
(again to prevent runtime errors). Furthermore, the documentation of the observe
method states
when the returned NSKeyValueObservation is deinited or invalidated, it will stop observing
This is why you need to keep a strong reference to the value returned by the observe
method.
Also, consider using the KeyPath notation I used here. If you make a typo, it will fail when compiling, instead of at runtime.
I hope this helps you out!