You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在super.init中引用self导致崩溃的技术解决方案问询

嘿,这个坑我之前踩过好几次!先给你明确结论:绝对不能在父类初始化(super.init)的传入闭包里引用self——哪怕加了weak修饰也不行,这完全是初始化流程里的“禁区”,你的崩溃就是因为这个原因。

为什么会崩溃?

Swift的初始化流程是有严格顺序的:

  1. 先初始化子类自己的所有存储属性
  2. 再调用父类的super.init完成父类部分的初始化
  3. 只有当super.init执行完成后,子类的实例才算是完全构建完成,self的状态才是稳定、安全的

你在super.init的闭包参数里引用self时,虽然子类的属性已经初始化了,但整个实例还处于“半完工”状态——内存布局可能还没完全确定,父类部分的初始化也没完成。这时候闭包里捕获的self是一个未完全初始化的实例,访问它就会触发未定义行为,表现出来就是随机的bad access崩溃(因为内存状态不稳定,有时候碰巧没触发,有时候就直接崩了)。

编译器没报错是因为它只做语法层面的检查,不会去验证初始化流程中的内存安全性,所以代码能编译过,但运行时必出问题。

怎么解决?

给你两个靠谱的方案,按需选择:

方案1:先完成父类初始化,再设置闭包

如果父类允许后续修改action属性,那先调用不带闭包的super.init,等self完全初始化后,再给action赋值:

class TextAlertView: ParentAlertView {
    let customText: String
    
    init(text: String) {
        self.customText = text
        // 先完成父类初始化,不传引用self的闭包
        super.init(action: nil)
        // 此时self已经完全安全了,再设置闭包
        self.action = { [weak self] in
            self?.handleAlertAction()
        }
    }
    
    func handleAlertAction() {
        print("触发了操作:\(customText)")
    }
}

方案2:提取需要的属性,避免捕获self

如果父类必须在初始化时就传入闭包,那可以把闭包需要用到的子类属性提前提取出来,让闭包捕获这个单独的属性,而不是self:

class TextAlertView: ParentAlertView {
    let customText: String
    
    init(text: String) {
        self.customText = text
        // 提前把需要的属性拿出来,闭包只捕获这个变量,不碰self
        let alertText = customText
        super.init(action: {
            print("触发了操作:\(alertText)")
        })
    }
}

最后再划重点

初始化阶段的self有严格的可用时机:只有在super.init执行完成后,才能安全地引用self。不管是闭包捕获还是直接调用方法,都要遵守这个规则,不然就会踩内存崩溃的坑。

内容的提问来源于stack exchange,提问作者Brandon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 10:18:06