简短回答:
您无法捕获和使用self
作为之前的值super.init
返回。就您而言,您正在尝试“通过”self
to super.init
作为一个论点。
至于为什么第二部分有效,只是因为不使用self
在其中,它没有捕获self
,因此它不使用self
作为一个值。
如果你不想使用self
在闭包中,那么你不需要担心strong
/weak
那里有参考,因为没有参考self
根本就在那里(因为它没有被捕获)。没有保留周期的危险。
关于“使用self
作为一个值” - 你可以使用self
在赋值的左侧来引用属性self
初始化它们时:
let myProperty: String
init(with myProperty: String) {
// this usage of self is allowed
self.myProperty = myProperty
super.init(nibName: nil, bundle: nil)
}
带有参考资料和内容的更长答案:
As per 文档:
安全检查4
初始化程序不能调用任何实例方法、读取任何实例属性的值或将 self 视为一个值直到第一阶段初始化完成后。
初始化的第一阶段通过调用结束super.init
, 当。。。的时候
来自同一文档:
Phase 1
在类上调用指定的或方便的初始值设定项。
为该类的新实例分配内存。内存尚未初始化。
该类的指定初始值设定项确认该类引入的所有存储属性都有一个值。这些存储属性的内存现已初始化。
指定的初始值设定项移交给超类初始值设定项,以对其自己的存储属性执行相同的任务。
这沿着类继承链继续向上,直到到达链的顶部。
一旦到达链的顶部,并且链中的最终类已确保其所有存储的属性都有值,则认为实例的内存已完全初始化,并且阶段 1 完成。
所以只有在打电话之后super.init
你可以使用self
作为值:
Phase 2
从链的顶部开始,链中的每个指定的初始化程序都可以选择进一步自定义实例。初始化程序现在能够访问 self 并可以修改其属性、调用其实例方法等。
最后,链中的任何便利初始化程序都可以选择自定义实例并使用self
.
现在,当你尝试使用时,我一点也不感到惊讶self
作为闭包捕获列表中的值,表明它崩溃了。更令我惊讶的是,编译器确实允许您这样做 - 现在我猜这是未实现错误处理的边缘情况。
在第二种情况下:
Action(title: "Yes", {
//Blank.. doesn't reference `self` in any way (weak, unowned, etc)
})
你并没有真正捕捉到self
,这就是它被允许并且有效的原因。但您无权访问self
那里。尝试添加一些使用的代码self
编译器会抱怨:
所以最后,如果你想使用self
在闭包中,您必须找到一种方法如何首先调用super.init
并且只有在那之后添加self
捕获属性的闭包。