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

时间:2016-09-02 23:22:14

标签: ios swift firebase firebase-authentication

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

@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()代码行之后,当前用户应为nil。但是当我在Xcode控制台中打印出当前用户时,当前用户仍然登录:

po FIRAuth.auth()?.currentUser
▿ Optional<FIRUser>
  - Some : <FIRUser: 0x7fde43540f50>

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

这可能是钥匙串问题吗?

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

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

6 个答案:

答案 0 :(得分:5)

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

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

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

答案 1 :(得分:2)

使用感叹号而不是问号。

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

答案 2 :(得分:2)

GIDSignIn.sharedInstance().signOut()

答案 3 :(得分:1)

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

我必须更改设置当前用户的逻辑,以便始终由Firebase提供的身份验证处理程序进行配置:

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)
        }

    }

}

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

答案 4 :(得分:0)

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

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

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

答案 5 :(得分:0)

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

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

for (i in 1:length(df$region)){
  if (nchar(df$region[i])==4) {
     df$region[i] <- paste0("0", df$region[i])
  }
}

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