我有以下代码(编辑:更新了代码,因此每个人都可以编译并查看):
import UIKit
struct Action
{
let text: String
let handler: (() -> Void)?
}
class AlertView : UIView
{
init(actions: [Action]) {
super.init(frame: .zero)
for action in actions {
// let actionButton = ActionButton(type: .custom)
// actionButton.title = action.title
// actionButton.handler = action.handler
// addSubview(actionButton)
}
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
class TextAlertView : AlertView
{
init() {
super.init(actions: [
Action(text: "No", handler: nil),
Action(text: "Yes", handler: { [weak self] in
//use self in here..
})
])
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
class MyViewController : UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let alert = TextAlertView()
view.addSubview(alert)
self.view = view
}
}
每次实例化时TextAlertView
,它都会super.init
因访问不当而崩溃。但是,如果我更改:
Action(title: "Yes", { [weak self] in
//use self in here..
})
至:
Action(title: "Yes", {
//Blank.. doesn't reference `self` in any way (weak, unowned, etc)
})
有用!
self
在超级初始化期间,有没有办法引用它是否弱于动作块内部(在上面,我在to的参数中进行了引用super.init
?
代码会编译..它只是在运行时随机崩溃。
简短答案:
您不能self
在super.init
返回之前捕获并用作值。在你的情况,你想“通” self
,以super.init
作为参数。
根据第二部分为什么起作用的原因,仅仅是因为不使用第二部分self
就不会捕获self
,因此它不会self
用作值。
如果您不想self
在闭包中使用,则不必担心那里的strong
/ weak
reference,因为根本没有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)
}
引用和资料的答案更长:
根据文档:
安全检查4
在初始化的第一阶段完成之前,初始化程序无法调用任何实例方法,读取任何实例属性的值或将self称为值。
初始化的第一阶段通过调用结束super.init
,当
从同一文档中:
阶段1
指定的或便捷的初始化程序在类上调用。
分配了该类新实例的内存。内存尚未初始化。
该类的指定初始化程序确认该类引入的所有存储属性都具有值。现在已初始化这些存储属性的内存。
指定的初始值设定项移交给超类初始值设定项,以为其自身的存储属性执行相同的任务。
这将继续类继承链,直到到达链的顶部。
一旦到达链的顶部,并且链中的最后一个类已确保其所有存储的属性都具有值,则实例的内存被视为已完全初始化,并且阶段1已完成。
因此,仅在调用后才super.init
允许您将其self
用作值:
阶段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
捕获闭包添加到属性后才能首先调用。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句