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

iOS应用启动时如何检查Firebase手机认证用户的登录状态?

Firebase手机号验证重启后登录状态未同步到UI的问题修复

问题根源

  1. 实例不统一:你在AppDelegate中创建了临时的UserManagerModel()实例并调用appLaunch_listener,但这个实例和UI层通过@EnvironmentObject依赖的实例是完全独立的两个对象。监听回调中修改的loggedIn变量只作用于临时实例,无法同步到UI使用的实例,导致UI无法感知登录状态变化。
  2. 线程问题:Auth.auth().addStateDidChangeListener的回调可能在后台线程执行,直接修改@Published变量可能无法正确触发UI更新。

修复步骤

1. 全局统一UserManagerModel实例

在App级别初始化唯一的UserManagerModel实例,并注入到SwiftUI环境中,确保所有UI组件共享同一个实例:

class AppDelegate: UIResponder, UIApplicationDelegate {
    var window: UIWindow?
    // 声明全局唯一的用户管理实例
    let userManager = UserManagerModel()

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
        FirebaseApp.configure()
        // 调用全局实例的监听方法
        userManager.appLaunch_listener()
        
        // 配置根视图并注入环境对象
        let contentView = LaunchView().environmentObject(userManager)
        window = UIWindow(frame: UIScreen.main.bounds)
        window?.rootViewController = UIHostingController(rootView: contentView)
        window?.makeKeyAndVisible()
        
        return true
    }
}

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

修改UserManagerModel的appLaunch_listener方法,将loggedIn的修改强制放在主线程执行:

func appLaunch_listener() {
    Auth.auth().addStateDidChangeListener({ auth, user in
        DispatchQueue.main.async {
            if user != nil {
                print("user is logged in")
                self.loggedIn = true
                print(self.loggedIn)
            } else {
                print("user is not logged in")
                self.loggedIn = false
            }
        }
    })
}

3. 优化登录验证后的状态同步(可选)

在verifyCode方法中,登录成功后主动设置loggedIn为true,确保UI及时响应:

func verifyCode(code: String, completion: @escaping (Error?) -> Void) {
    let verificationId = UserDefaults.standard.string(forKey: Constants.verificationIdStorageKey) ?? ""
    let credential = PhoneAuthProvider.provider().credential(withVerificationID: verificationId, verificationCode: code)
    
    Auth.auth().signIn(with: credential) { authResult, error in
        DispatchQueue.main.async {
            if error == nil {
                self.userInfo()
                self.loggedIn = true // 登录成功后主动更新状态
            }
            completion(error)
        }
    }
}

4. 优化LaunchView初始加载体验(可选)

由于Firebase状态监听是异步的,应用启动时loggedIn初始为false,可能会短暂显示登录界面。可以添加加载状态优化:

struct LaunchView: View {
    @EnvironmentObject var userManager : UserManagerModel
    @State private var isLoading = true

    var body: some View {
        Group {
            if isLoading {
                ProgressView("加载中...")
            } else if userManager.loggedIn {
                HomeView()
                    .onAppear{
                        userManager.userInfo()
                    }
            } else {
                userManager.newUser ? OnboardingView() : LoginForm()
            }
        }
        .onAppear {
            DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
                isLoading = false
            }
        }
    }
}

关键说明

  • 必须保证整个应用中只使用同一个UserManagerModel实例,环境对象的核心作用就是共享单一实例。
  • @Published变量的修改必须在主线程执行,否则无法触发SwiftUI的UI更新机制。
  • Firebase的addStateDidChangeListener会在应用启动时自动触发一次回调,无需额外手动检查用户状态。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 02:06:25