Swift中如何在结构体/类中引用其他类避免运行错误
拆分ObservableObject方法到子模块的正确实现
现有代码的核心问题
FirebaseAuthModel内部错误声明了var fb = FirebaseAuthModel(),会触发无限递归创建实例,直接导致栈溢出,这是你出现EXC_BAD_ACCESS的直接原因- 即使修正为
var fb = FirebaseModel(),这个实例是全新创建的,和你在View中使用的FirebaseModel实例不是同一个,修改它的signedIn属性完全不会触发UI更新 - 如果两个实例互相强持有,会出现循环引用,导致内存泄漏,也可能在实例释放后触发野指针崩溃
修正后的实现代码
首先调整拆分的子结构体:
import FirebaseAuth struct FirebaseAuthModel { // 弱持有父类实例,避免循环引用 weak var parent: FirebaseModel? func signIn(email: String, password: String) { let auth = Auth.auth() auth.signIn(withEmail: email, password: password) { [weak self] result, error in // 异步回调先判空,避免野指针 guard let self = self, error == nil else { return } self.parent?.signedIn = true } } }
然后调整父类ObservableObject的实现:
import Combine class FirebaseModel: ObservableObject { @Published var signedIn: Bool = false let auth: FirebaseAuthModel init() { // 初始化时将自身引用传递给子模块,保证操作的是同一个实例 self.auth = FirebaseAuthModel(parent: self) } }
调用方式
完全符合你的预期,View中直接按原有方式调用即可:
import SwiftUI struct LoginView: View { @StateObject private var fb = FirebaseModel() var body: some View { VStack { // 登录状态变化会自动刷新UI if fb.signedIn { Text("已登录") } else { Button("登录") { fb.auth.signIn(email: "xxx@xx.com", password: "xxxxxx") } } } } }
避免EXC_BAD_ACCESS的核心要点
- 拆分出的子模块持有父类引用必须加
weak修饰,禁止强持有父类实例 - 所有异步回调中必须使用
[weak self]捕获当前实例,执行操作前先判空,避免实例已经释放后仍执行操作 - 禁止在子模块中单独创建父类的新实例,所有子模块的父类引用都从父类初始化时传入
内容的提问来源于stack exchange,提问作者Joonaynay
相关产品推荐
相关产品推荐

