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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 08:24:03