Firebase – iOS Swift:FIRAuth.auth()。signOut()未注销当前用户

我正在使用Firebase构建一个应用程序,其中包含一个初始SignInViewController ,用于加载登录页面,供用户通过电子邮件进行身份validation,从而触发以下方法:

 @IBAction func didTapSignIn(sender: AnyObject) { let email = emailField.text let password = passwordField.text FIRAuth.auth()?.signInWithEmail(email!, password: password!) { (user, error) in if let error = error { print(error.localizedDescription) return } self.signedIn(user!) } } func signedIn(user: FIRUser?) { AppState.sharedInstance.displayName = user?.displayName ?? user?.email AppState.sharedInstance.signedIn = true NSNotificationCenter.defaultCenter().postNotificationName(Constants.NotificationKeys.SignedIn, object: nil, userInfo: nil) performSegueWithIdentifier(Constants.Segues.SignInToHome, sender: nil) } 

SignInViewController还会在应用程序启动时检查是否存在缓存的当前用户,如果是,则在以下位置标记该用户:

 override func viewDidAppear(animated: Bool) { super.viewDidAppear(true) //Synchronously gets the cached current user, or null if there is none. if let user = FirebaseConfigManager.sharedInstance.currentUser { self.signedIn(user) } } 

用户登录后,应用程序将转到HomeScreenViewController ,该控件在导航栏的左上角显示“注销”按钮。 当用户点击“注销”按钮时,该用户应该退出,应用程序应该使用以下方法返回到SignInViewController

 @IBAction func didTapSignOut(sender: UIBarButtonItem) { print("sign out button tapped") let firebaseAuth = FIRAuth.auth() do { try firebaseAuth?.signOut() AppState.sharedInstance.signedIn = false dismissViewControllerAnimated(true, completion: nil) } catch let signOutError as NSError { print ("Error signing out: \(signOutError)") } catch { print("Unknown error.") } } 

当我点击“退出”按钮时, didTapSignOut方法被调用并被执行。 但是,在try firebaseAuth?.signOut()执行try firebaseAuth?.signOut()代码行之后,当前用户应为nil 。 但是当我在Xcode控制台中打印出当前用户时,当前用户仍然登录:

 po FIRAuth.auth()?.currentUser ▿ Optional - Some :  

由于当firebaseAuth?.signOut()被调用后当前用户没有firebaseAuth?.signOut() ,一旦应用程序回到SignInViewController ,应用程序仍然认为有一个缓存的当前用户,以便用户再次登录。

这可能是钥匙串问题吗?

是否与NSNotificationCenter.defaultCenter().postNotificationName被调用有关?

我的代码直接来自Google Firebase Swift Codelab,所以我不确定它为什么不起作用: https : //codelabs.developers.google.com/codelabs/firebase-ios-swift/#4

您可以在视图控制器的viewDidAppear方法中添加一个侦听器,如下所示:

 FIRAuth.auth()?.addStateDidChangeListener { auth, user in if let user = user { print("User is signed in.") } else { print("User is signed out.") } } 

这允许您在用户的身份validation状态更改时执行代码。 它允许您监听事件,因为Firebase中的signOut方法没有完成处理程序。

使用感叹号而不是问号。

  try! FIRAuth.auth()!.signOut() 
 GIDSignIn.sharedInstance().signOut() 

我实际上也有这个问题。 我还使用Firebase提供的方法注销了用户(就像你一样)但是当我打印到控制台时它说我还有一个可选用户。

我不得不更改设置当前用户的逻辑,以便始终由Firebase提供的身份validation处理程序配置:

 var currentUser: User? = Auth.auth().currentUser var handle: AuthStateDidChangeListenerHandle! init() { handle = Auth.auth().addStateDidChangeListener { (auth, user) in self.currentUser = user if user == nil { UserDefaults.standard.setValue(false, forKey: UserDefaults.loggedIn) } else { UserDefaults.standard.setValue(true, forKey: UserDefaults.loggedIn) } } } 

只要您从此句柄引用当前用户,无论身份validation状态如何,它都将更新当前用户。

我刚刚遇到了同样的问题 – Firebase + Swift 3在注销时不会触发stateDidChangeListeners ,这让我的应用程序认为用户仍然登录。

最终为我工作的是保存FIRAuth.auth()用对FIRAuth.auth()实例的单个引用,而不是每次都调用FIRAuth.auth()。

调用FIRAuth.auth()?.signOut()不会触发我之前附加的stateDidChangeListeners 。 但是当我保存变量并在两种方法中重用它时,它按预期工作。

当firebase注销方法可能引发错误时,一些答案正在使用强制解包。 不要这样做!

相反,调用应该在do-catch-block中完成,如下所示

  do { try Auth.auth().signOut() } catch let error { // handle error here print("Error trying to sign out of Firebase: \(error.localizedDescription)") } 

然后,您可以使用Auth.auth()。addStateDidChangeListener并相应地处理状态更改。