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

Swift初始化时如何在类间传递函数?解决self未初始化报错

Swift类间数据传递的初始化错误解决方法

你遇到的'self' used before all stored properties are initialized错误,核心原因是ClassB初始化时,在所有存储属性未完成初始化前,就通过传递实例方法classBMethod隐式引用了self,同时代码还存在ClassA与ClassB互相持有导致的循环引用风险。以下是两种可行的修复方案:


方案一:使用延迟初始化(lazy)+ 弱引用捕获

将classAInstance声明为lazy属性,让它在ClassB完成初始化后再创建,同时在闭包中用weak self避免循环引用:

class ClassA {
    let closure: (Int) -> Void

    init(closure: @escaping (Int) -> Void) {
        self.closure = closure
    }

    func fetchData() {
        // 模拟异步/定时获取数据
        let exampleData = 1234
        closure(exampleData)
    }
}

class ClassB {
    // 延迟初始化ClassA实例,确保self已完全初始化
    lazy var classAInstance: ClassA = {
        ClassA(closure: { [weak self] value in
            self?.classBMethod(value: value)
        })
    }()
    var data: Int

    init() {
        // 先初始化所有存储属性
        data = 0
    }

    func classBMethod(value: Int) {
        print("Value is \(value)")
        data = value
    } 
}

// 调用示例
let classB = ClassB()
classB.classAInstance.fetchData()

说明:

  • lazy关键字让classAInstance在第一次被访问时才初始化,此时ClassB的所有存储属性已完成赋值,self可用。
  • [weak self]弱引用捕获,避免ClassA持有闭包、闭包持有ClassB的循环引用问题,防止内存泄漏。

方案二:将ClassB的闭包改为可选类型,延迟赋值

调整ClassA的结构,把closure设为可选属性,等ClassB完成所有属性初始化后再赋值:

class ClassA {
    // 改为可选闭包,允许先初始化实例再赋值
    var closure: ((Int) -> Void)?

    init() {}

    func fetchData() {
        let exampleData = 1234
        // 可选链式调用,避免闭包未赋值时崩溃
        closure?(exampleData)
    }
}

class ClassB {
    let classAInstance: ClassA
    var data: Int

    init() {
        // 先初始化所有存储属性
        data = 0
        classAInstance = ClassA()
        // 此时self已完全初始化,可安全赋值闭包
        classAInstance.closure = { [weak self] value in
            self?.classBMethod(value: value)
        }
    }

    func classBMethod(value: Int) {
        print("Value is \(value)")
        data = value
    } 
}

// 调用示例
let classB = ClassB()
classB.classAInstance.fetchData()

说明:

  • 先完成ClassB所有存储属性的初始化,再给ClassA的closure赋值,避免self未就绪的问题。
  • 同样使用[weak self]解决循环引用,确保内存管理安全。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 07:55:30