Suppose you have a class
class Cell: UITableViewCell
{
var button: UIButton =
{
let obj = UIButton()
obj.translatesAutoresizingMaskIntoConstraints = false
obj.addTarget(self, action: #selector(didTapBtn), for: .touchUpInside)
return obj
}()
init()
{
super.init(style: .default, reuseIdentifier: "identifier")
//other configurations for UI
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
@objc func didTapBtn()
{
print("btn tapped")
}
}
If your table view deque a reusable cell, and you then tap the button it does not work. Here var button has to be a lazy var button in order for it to work. (or you must specify the addTarget when self is created in initializer)
By this I understand that whenever we addTarget to a UIButton, self object has to be initialised at the time of adding target (so it does find self in target).
But when we write the similar code for UIViewController, like
class Controller: UIViewController
{
var button: UIButton =
{
let obj = UIButton()
obj.translatesAutoresizingMaskIntoConstraints = false
obj.addTarget(self, action: #selector(didTapBtn), for: .touchUpInside)
return obj
}()
init()
{
super.init(nibName: nil, bundle: nil)
//other ui configurations
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
@objc func didTapBtn()
{
print("btn tapped")
}
}
Then it is now not necessary for a UIButton to be lazy var, we can keep addTarget as it is in trailing closure of var button, where that closure even runs before initializer and that button target will still work.
What is actually going on behind the scenes, the first way in UITableViewCell class has to be the correct behaviour according to me as self should not be available, before the initialization of the object is done. But how does that addTarget works for a UIViewController class ?