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
相关产品推荐
相关产品推荐

