[英]Swift - `self` in variable initialization closure
没有lazy
关键字的button.addTarget(self, action: #selector(taptap), for: .touchUpInside)
工作?
错误地lazy
了,并关闭了一个初始化按钮,如下所示:
class MyView: UIView {
let button: UIButton = {
let button = UIButton()
button.addTarget(self, action: #selector(taptap), for: .touchUpInside)
print(self) // (Function)
// button.frame = bounds <- Cannot assign here
return button
}()
lazy var button2: UIButton = {
let button = UIButton()
print(self) // <sample.MyView ...>
return button
}()
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
addSubview(button2)
addSubview(button)
button.frame = bounds
print(self) // <sample.MyView ...>
}
@objc func taptap() {
print("taptap")
}
}
且打印结果为:
(Function)
<sample.MyView: 0x7f961dd09d80; frame = (67 269; 240 128); autoresize = RM+BM; layer = <CALayer: 0x6080000268a0>>
<sample.MyView: 0x7f961dd09d80; frame = (67 269; 240 128); autoresize = RM+BM; layer = <CALayer: 0x6080000268a0>>
taptap
有什么区别self
按钮关闭和self
的人? 为什么我的按钮可以使用?
简而言之,当您使用闭包初始化声明实例属性时,该属性将在self
可用之前创建(在实例正确初始化之前),因此无法访问self
。 lazy
实例属性只能在实例初始化后才能访问,因此您可以从lazy
属性访问self
。
较长版本:
如果通过let button: UIButton = { return UIButton() }()
使用闭包初始化,则将在运行时以完全相同的方式处理button
变量,就像您像let button:UIButton = UIButton()
那样简单地声明它一样。 注意闭包末尾的()
。 当实例属性被初始化时,这实际上立即执行了闭包,这就是为什么实际上可以将其声明为不可变的原因。 由于实例属性是在调用类初始值设定项之前进行初始化的,因此self
在属性的闭包内不可用。
使用lazy
关键字声明变量时,仅在首次访问该变量时才对其进行求值。 因此, self
在闭包内部可以声明一个lazy
属性,因为在创建类实例之前无法访问该属性,因此在所有情况下, self
都已经初始化,并且在您访问惰性属性时就可以使用属性。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.