I am trying to have my UILabel's text automatically update in increments of 1 based on a looping Timer. The label is linked to a variable. I'm not sure if it matters but I am doing my UI programmatically using auto layout anchors.
I understand this is not working because the variable lives outside of ViewDidLoad(). I also tried setting up a subclass of a UILabel in a separate file but I could not figure out the proper way to do that. I was having trouble connecting the variable to the subclass and properly implementing didSet.
Here is the relevant code from my View Controller, any recommendations or alternative methods are appreciated.
import UIKit
class ViewController: UIViewController {
var numberOfBreaths = 0
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
let breathCounter = UILabel()
breathCounter.translatesAutoresizingMaskIntoConstraints = false
breathCounter.text = "\(numberOfBreaths)"
breathCounter.textAlignment = .center
breathCounter.center = self.view.center
// Irrelevant hidden label code redacted
let startStop = RoundButton()
startStop.translatesAutoresizingMaskIntoConstraints = false
startStop.backgroundColor = .white
startStop.setTitle("breathe", for: .normal)
startStop.setTitleColor(.darkGray , for: .normal)
startStop.layer.borderWidth = 2.5
startStop.layer.borderColor = CGColor(red: 225, green: 225, blue: 0, alpha: 1)
startStop.addTarget(self, action: #selector(self.breathCount), for: .touchUpInside)
view.addSubview(breathCounter)
view.addSubview(holdTimer)
view.addSubview(startStop)
// Anchor code redacted
}
@objc func breathCount(_ sender: RoundButton) {
print("Button Tapped")
createTimer()
}
func createTimer() {
_ = Timer.scheduledTimer(timeInterval: 3.5, target: self, selector: #selector(nextBreath), userInfo: nil, repeats: true)
}
@objc func nextBreath() {
numberOfBreaths += 1
breathCounter.text = "\(numberOfBreaths)" // Error: Cannot find 'breathCounter' in scope
print(numberOfBreaths) // Prints expected number to console
}
}
If you declare breathCounter
as a property on your view controller (like you did for numberOfBreaths
, you will have access to it from both the viewDidLoad
and nextBreath
functions. I'd also hold a reference to your Timer
class ViewController: UIViewController {
var numberOfBreaths = 0
let breathCounter = UILabel()
var timer : Timer?
And then inside viewDidLoad
, remove the existing let breathCounter = UILabel()
line.
And inside createTimer
:
self.timer = Timer.scheduledTimer(timeInterval: 3.5, target: self, selector: #selector(nextBreath), userInfo: nil, repeats: true)