If you define a UILabel programmatically, it must be done so in viewDidLoad()
? But, if you were to define a #selector
method that needed to set said label, it would be impossible given that the @objc
selector method needs to be outside the scope of the viewDidLoad()
method, where it cannot access the label. How do you get around this?
class ViewController: UIViewController {
var count = 4
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
let label = UILabel(frame: CGRect(x: 0, y: 0, width: 150, height: 150))
label.center = CGPoint(x: 250, y: 430)
label.font = .systemFont(ofSize: 130)
label.textColor = UIColor.black
view.addSubview(label)
Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: <#T##Selector#>, userInfo: <#T##Any?#>, repeats: <#T##Bool#>)
@objc func updateLabel() { // ERROR @objc can only be used with members of classes...
if count > 0 {
count -= 1
label.text = "\(count)"
}
}
}
}
Your mistake is that you have put the selector updateLabel
inside of viewDidLoad
. You should put it outside viewDidLoad
so that it is a member of your class, rather than a local function.
To access the label in updateLabel
, simply move the declaration of the label outside of both methods.
You should also add a timer
parameter to updateLabel
so that you can stop the timer when count
reaches 0, rather than keeping the timer running forever.
var label: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
label = UILabel(frame: CGRect(x: 0, y: 0, width: 150, height: 150))
label.center = CGPoint(x: 250, y: 430)
label.font = .systemFont(ofSize: 130)
label.textColor = UIColor.black
view.addSubview(label)
Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(updateLabel), userInfo: nil, repeats: true)
}
@objc func updateLabel(_ timer: Timer) {
if count > 0 {
count -= 1
label.text = "\(count)"
} else {
timer.invalidate()
}
}