在super.init中引用self

布兰登

我有以下代码(编辑:更新了代码,因此每个人都可以编译并查看):

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

代码会编译..它只是在运行时随机崩溃。

米兰诺萨

简短答案

您不能selfsuper.init返回之前捕获并用作值在你的情况,你想“通” self,以super.init作为参数。

根据第二部分为什么起作用的原因,仅仅是因为不使用第二部分self就不会捕获self,因此它不会self用作值。

如果您不想self在闭包中使用,则不必担心那里的strong/ weakreference,因为根本没有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] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

为什么在多次继承中执行Base .__ init __(self)而不是super().__ init __()时会跳过__init__?

只要init调用[super init],在Objective C自定义init方法中调用[self init]是否可以?

为什么Visual Studio Code会在派生类中插入“ return super().__ init __(self)”?

在Objective-C中,为什么要检查self = [super init]是否不为零?

迅速在super.init调用中未初始化属性“ self.title”

在if((self = [super init]))中未检测到cocos2d冲突

Python中super()和super(className,self)之间的区别

super.init调用未初始化属性“ self。*”

为什么self = [super init]确保单例模式?

为什么super().__ init__没有自我引用?

为什么在“ super(A,self)”中,对象先于“ self”?

Swift super.init() - 属性未在 super.init 调用中初始化

super().__ init__覆盖属性

Java中的super()

构造函数中的super()

JAVA中的super()函数

init快速让子类中引用self的属性

在super.init初始化self之前,在属性访问“ frame”中使用“ self”

为什么 super().__init__ () 的行为与 Python 派生类中的 super().override() 不同?

在super中定义的常量不能在子类的super.init中使用?

python-在super()中访问超类的class属性。__init __()

调用super的init时,Python中的最大递归深度错误。

属性未在super.init调用中初始化

我不理解在我的代码中未在super.init调用错误中初始化的属性'self.heading'

将super()与Java中的引用一起使用

错误:“物业‘self.gameArea’在super.init通话不会被初始化”

通过super.init调用可以在'catch'块中使用'self'

在“super.init”调用之前在方法调用“foo”中使用“self”

片段中的super.onCreateView