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

Swift从Firebase获取登录用户数据失败,模拟器报EXC_BAD_ACCESS错误

问题分析与修复方案

你的代码出现Thread 1: EXC_BAD_ACCESS崩溃,通常是内存访问错误,结合Firebase登录和数据获取逻辑,主要排查以下几个关键点:

1. @AppStorage 不直接支持URL类型

@AppStorage默认仅支持基础数据类型(字符串、数字、布尔值等),直接存储URL?会导致内存解析错误。需要给URL添加RawRepresentable扩展实现类型转换:

extension URL: RawRepresentable {
    public init?(rawValue: String) {
        guard let url = URL(string: rawValue) else { return nil }
        self = url
    }
    
    public var rawValue: String {
        absoluteString
    }
}

修改LoginView中的profileURL声明:

@AppStorage("user_profile_url") var profileURL: URL? = nil

2. 缺失错误处理导致状态异常

loginUser和fetchUser方法的do-catch块未处理错误,会导致错误被静默忽略,进而引发内存或状态紊乱:

func loginUser(){
    isLoading = true
    closeKeyboard()
    Task{ [weak self] in
        guard let self = self else { return }
        do{
            try await Auth.auth().signIn(withEmail: self.emailID, password: self.password)
            print("User Found")
            try await self.fetchUser()
        } catch {
            await self.setError(error)
        }
    }
}

func fetchUser()async throws{
    guard let userID = Auth.auth().currentUser?.uid else{
        throw NSError(domain: "AuthError", code: -1, userInfo: [NSLocalizedDescriptionKey: "未找到当前登录用户"])
    }
    let user = try await Firestore.firestore().collection("Users").document(userID).getDocument(as: User.self)
    await MainActor.run(body: {
        userUID = userID
        userNameStored = user.username
        profileURL = user.userProfileURL
        logStatus = true
        isLoading = false // 登录成功后结束加载状态
    })
}

3. Firebase初始化时机优化

在App的init中直接调用FirebaseApp.configure()可能存在线程安全问题,改用@StateObject管理Firebase初始化更符合SwiftUI生命周期:

class FirebaseManager: ObservableObject {
    static let shared = FirebaseManager()
    
    init() {
        FirebaseApp.configure()
    }
}

@main
struct LoginForiOS: App {
    @StateObject private var firebaseManager = FirebaseManager()
    
    var body: some Scene {
        WindowGroup {
            ContentView()
                .environmentObject(firebaseManager)
        }
    }
}

4. 检查User模型的Codable实现

fetchUser中使用getDocument(as: User.self)依赖User模型正确实现Codable,确保字段名和类型与Firestore中的数据完全匹配:

struct User: Codable, Identifiable {
    let id: String
    let username: String
    let userProfileURL: URL?
    
    // 对应Firestore中的字段名,需根据实际调整
    enum CodingKeys: String, CodingKey {
        case id = "uid"
        case username
        case userProfileURL = "profile_url"
    }
}

5. UI操作强制在主线程执行

closeKeyboard这类UI操作必须在主线程完成,避免线程冲突:

func closeKeyboard() {
    DispatchQueue.main.async {
        UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 09:05:14