如何解决Firebase状态监听器重复触发导致页面多次跳转的问题
问题原因
你遇到的重复弹窗问题来源于两个逻辑漏洞:
- 双重路由触发:你既注册了全局的
Auth状态变更监听,又在登录请求的独立回调里单独调用了showNextVC。当登录操作成功时,Firebase Auth的状态发生变更,会先触发signingManager里的监听回调执行一次跳转;紧接着登录接口自己的完成回调也会执行,第二次触发跳转,最终就出现了两个VC叠加的情况。 - 登录回调逻辑错误:当前登录请求的完成回调里,就算用户登录成功
user != nil的分支执行完毕,代码不会中断,会继续往下走执行displayWarningLabel(withText: "no such user"),也就是登录成功的同时还会弹出不存在用户的错误提示,这个是隐藏的逻辑漏洞。
修复方案
- 所有登录状态变更后的跳转逻辑统一交给状态监听处理,删除登录回调里的
showNextVC调用,避免重复触发 - 修复登录回调的分支逻辑,避免成功后还执行错误提示
- 建议在页面销毁时移除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
相关产品推荐
相关产品推荐

