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

登录/注册后MainTabView无法获取currentUser导致加载异常求助

嘿,我看了你的代码和问题描述,这个间歇性的loading和崩溃问题大概率是异步逻辑的时序和主线程更新的问题导致的,我帮你拆解下问题点和修复方案:

问题根源分析

  • 注册后未主动拉取用户数据:你的register方法里创建用户并写入Firestore后,没有调用fetchUser(),只有登录和App初始化时才会拉取用户数据。这就导致注册完成后currentUser还是nil,直接进入MainTabView的else分支显示loading,只有下次启动App时才会加载用户信息。
  • 异步回调未在主线程更新UI:Firebase的Auth和Firestore回调都是在后台线程执行的,而SwiftUI的@Published变量必须在主线程更新,否则会导致UI更新异常,甚至出现崩溃的情况。
  • fetchUser的错误处理缺失:当Firestore文档不存在或者解析失败时,没有任何处理逻辑,会导致currentUser一直处于nil状态,持续显示loading。
  • 头像上传后的用户数据不同步:注册时上传头像并更新Firestore后,没有重新拉取用户数据,导致AccountView里的头像URL可能不是最新的。

具体修复方案

1. 修复register方法,补全fetchUser并确保主线程更新

修改AuthViewModel里的register方法,在写入Firestore成功后调用fetchUser,同时把更新userSession的操作放到主线程:

func register(withEmail email: String, password: String, fullname: String) {
    Auth.auth().createUser(withEmail: email, password: password) { [weak self] result, error in
        guard let self = self else { return }
        
        if let error = error {
            print("DEBUG: Failed to register with error \(error.localizedDescription)")
            return
        }
        
        guard let user = result?.user else { return }
        
        // 主线程更新userSession,确保UI及时响应
        DispatchQueue.main.async {
            self.userSession = user
        }

        let data: [String: Any] = ["email": email,
                                   "fullname": fullname]
        
        COLLECTION_USERS
            .document(user.uid)
            .setData(data) { [weak self] error in
                guard let self = self else { return }
                if let error = error {
                    print("DEBUG: Failed to save user data \(error.localizedDescription)")
                    return
                }
                // 数据写入成功后拉取用户信息
                self.fetchUser()
                self.uploadProfileImage(self.selectedImage)
            }
    }
}

2. 确保所有@Published变量的更新在主线程

修改login、fetchUser、signOut方法,把更新userSession和currentUser的操作都放到主线程,同时补全错误处理:

func login(withEmail email: String, password: String) {
    Auth.auth().signIn(withEmail: email, password: password) { [weak self] result, error in
        guard let self = self else { return }
        
        if let error = error {
            print("DEBUG: Failed to sign in with error \(error.localizedDescription)")
            return
        }
        
        guard let user = result?.user else { return }
        
        DispatchQueue.main.async {
            self.userSession = user
        }
        self.fetchUser()
    }
}

func fetchUser() {
    guard let uid = userSession?.uid else { return }
    
    COLLECTION_USERS.document(uid).getDocument { [weak self] snapshot, error in
        guard let self = self else { return }
        
        if let error = error {
            print("DEBUG: Failed to fetch user \(error.localizedDescription)")
            // 拉取失败时清除userSession,回到登录页
            DispatchQueue.main.async {
                self.userSession = nil
            }
            return
        }
        
        guard let snapshot = snapshot, snapshot.exists else {
            print("DEBUG: User document does not exist")
            DispatchQueue.main.async {
                self.userSession = nil
            }
            return
        }
        
        do {
            let user = try snapshot.data(as: User.self)
            DispatchQueue.main.async {
                self.currentUser = user
            }
        } catch {
            print("DEBUG: Failed to parse user data \(error.localizedDescription)")
        }
    }
}

func signOut() {
    DispatchQueue.main.async {
        self.userSession = nil
    }
    do {
        try Auth.auth().signOut()
    } catch {
        print("DEBUG: Failed to sign out \(error.localizedDescription)")
    }
}

3. 修复头像上传后的用户数据同步

在头像上传完成并更新Firestore后,重新拉取用户数据,确保UI显示最新的头像:

func uploadProfileImage(_ image: UIImage?) {
    guard let uid = userSession?.uid else { return }
    
    ImageUploader.uploadImage(image: image) { [weak self] profileImageUrl in
        guard let self = self else { return }
        
        COLLECTION_USERS
            .document(uid)
            .updateData(["profileImageUrl": profileImageUrl]) { [weak self] error in
                guard let self = self else { return }
                if let error = error {
                    print("DEBUG: Failed to update profile image \(error.localizedDescription)")
                    return
                }
                // 更新头像后重新拉取用户数据
                self.fetchUser()
            }
    }
}

4. 优化MainTabView的loading状态(可选)

把纯文本的loading换成系统自带的加载指示器,体验更友好:

struct MainTabView: View {
    @State private var selectedIndex = 0
    @EnvironmentObject var viewModel: AuthViewModel
    
    var body: some View {
        Group {
            if let user = viewModel.currentUser {
                TabView(selection: $selectedIndex) {
                    ExploreView()
                        .onTapGesture { self.selectedIndex = 0 }
                        .tabItem { Image(systemName: "house") }.tag(0)
                    
                    SearchView()
                        .onTapGesture { self.selectedIndex = 1 }
                        .tabItem { Image(systemName: "magnifyingglass") }.tag(1)
                    
                    ConversationsView()
                        .onTapGesture { self.selectedIndex = 2 }
                        .tabItem { Image(systemName: "message") }.tag(2)
                    
                    AccountView(user: user)
                        .onTapGesture { self.selectedIndex = 3 }
                        .tabItem { Image(systemName: "person.crop.circle") }.tag(3)
                }
            } else {
                ProgressView("Loading...")
                    .progressViewStyle(CircularProgressViewStyle())
            }
        }
    }
}

额外小建议

  • 用[weak self]避免循环引用,防止内存泄漏
  • 所有Firebase回调都要处理错误,方便调试和给用户提示
  • 拉取用户数据失败时自动清除userSession,避免用户一直卡在loading状态

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 18:15:35