Swift - 变量初始化闭包中的`self`

时间:2018-03-26 12:03:47

标签: swift swift4 self

button.addTarget(self, action: #selector(taptap), for: .touchUpInside) 如何在没有lazy关键字的情况下工作?

错误地删除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有什么区别?为什么我的按钮有效?

2 个答案:

答案 0 :(得分:2)

简而言之,当您使用闭包初始化声明实例属性时,将在 return out("friendship").aggregate("x") .out("friendship") .where(P.without("x")) .groupCount() .by("email") .order(Scope.local) .by(Column.values, Order.decr) .limit(Scope.local, limit); 可用之前创建该属性(在实例正确初始化之前),因此您无法访问self。只有在实例初始化后才能访问self实例属性,因此您可以从lazy属性访问self

更长的版本:

如果您使用lazy的闭包初始化,let button: UIButton = { return UIButton() }()变量将在运行时以完全相同的方式处理,就像您只是将其声明为button一样。在关闭结束时注意let button:UIButton = UIButton()。这实际上是在初始化实例属性时立即执行闭包,这就是它实际上可以被声明为不可变的原因。由于在调用类初始化程序之前初始化实例属性,因此在属性的闭包内不能使用()

使用self关键字声明变量时,只会在首次访问时对其进行评估。因此,lazy在闭包内可用,声明self属性,因为在创建类实例之前无法访问属性,因此在所有情况下,{ {1}}已初始化,并且在您访问懒惰媒体资源时可用。

答案 1 :(得分:2)

它适用于NSObject个子类,因为NSObject(或更确切地说NSObjectProtocol)声明了方法self。该方法也适用于元类型(也是NSObject个实例),因此您可以在静态上下文中调用它。

它实际上适用于UIButton的事实可能是编译器的一个怪癖,以及UIButton接受Any?作为目标的事实。

不要使用它,而不是它的工作方式。

查看错误SR-4559