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

如何解决Firebase状态监听器重复触发导致页面多次跳转的问题

问题原因

你遇到的重复弹窗问题来源于两个逻辑漏洞:

  • 双重路由触发:你既注册了全局的Auth状态变更监听,又在登录请求的独立回调里单独调用了showNextVC。当登录操作成功时,Firebase Auth的状态发生变更,会先触发signingManager里的监听回调执行一次跳转;紧接着登录接口自己的完成回调也会执行,第二次触发跳转,最终就出现了两个VC叠加的情况。
  • 登录回调逻辑错误:当前登录请求的完成回调里,就算用户登录成功user != nil的分支执行完毕,代码不会中断,会继续往下走执行displayWarningLabel(withText: "no such user"),也就是登录成功的同时还会弹出不存在用户的错误提示,这个是隐藏的逻辑漏洞。

修复方案

  1. 所有登录状态变更后的跳转逻辑统一交给状态监听处理,删除登录回调里的showNextVC调用,避免重复触发
  2. 修复登录回调的分支逻辑,避免成功后还执行错误提示
  3. 建议在页面销毁时移除Auth状态监听,避免内存泄漏和不必要的后续回调触发

修复后的登录按钮逻辑

@IBAction func logInTapped(_ sender: UIButton) {
    guard let email = emailTextField.text, let password = passwordTextField.text, !email.isEmpty, !password.isEmpty else {
        displayWarningLabel(withText: "info is incorrect")
        return
    }
    Auth.auth().signIn(withEmail: email, password: password, completion: { [weak self] (user, error) in
        guard let self = self else { return }
        if let error = error {
            self.displayWarningLabel(withText: "error occured: \(error.localizedDescription)")
            return
        }
        // 跳转逻辑统一交给状态监听处理,此处无需重复调用
        print("Congratulations, you have successfully logged in!")
    })
}

状态监听优化(增加移除逻辑)

首先在当前控制器中声明监听句柄属性:

var authListenerHandle: AuthStateDidChangeListenerHandle?

修改signingManager方法存储监听句柄:

func signingManager(){
    authListenerHandle = Auth.auth().addStateDidChangeListener { [weak self] (auth, user) in
        guard let self = self else {return}
        if user != nil {
            self.showNextVC()
            print("You are already entered")
        }
    }
}

在控制器销毁时移除监听:

deinit {
    if let handle = authListenerHandle {
        Auth.auth().removeStateDidChangeListener(handle)
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 00:06:02