2016-09-02 3 views
4

Я создаю приложение с использованием Firebase с начальным SignInViewController, которое загружает страницу входа для проверки подлинности с помощью электронной почты, которая запускает следующие методы:Firebase - iOS Swift: FIRAuth.auth(). SignOut() не выписывает текущего пользователя

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

После того как пользователь вошел в систему, что приложение segues на 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

+0

http://stackoverflow.com/a/39170080/6297658 – Dravidian

+0

Спасибо @ Дравидиану, я посмотрю. – alexisSchreier

+0

@ Дравидий, спасибо за ссылку. Однако даже когда я пытаюсь распечатать currentUser в методе viewWillAppear (анимированный: Bool) после того, как приложение перейдет на страницу входа, текущий пользователь не равен нулю. Вы говорите, что из-за асинхронного завершения метода .signOut() пользователь не получает вход вовремя до того, как метод viewWillAppear (анимированный: Bool) проверяет, включен ли этот пользователь? Если да, то как я должен выполнить проверку для текущего пользователя ** только если ** метод signOut() был успешным? – alexisSchreier

ответ

2

Используйте восклицательные не знаки вопроса.

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

Спасибо за ваш ответ @rMickeyD. Я все равно получаю тот же результат. Я редактировал мой код, чтобы попробовать! FIRAuth.auth() !. signOut() 'как вы предлагали, но текущий пользователь все еще существует в кеше, когда viewWillAppear (анимированный: Bool) вызывается и проверяет пользователя в' SignInViewController'. – alexisSchreier

+0

never Force unwrap ('!') 'Try', ваше приложение выйдет из строя, если вы нажмете разворот, а' signOut' столкнется с ошибкой. Например, 'signOut' будет определенно вызывать ошибку, если у пользователя нет подключения к интернету (или в режиме полета), в этом случае ваше приложение, безусловно, сбой. – Annjawn

2

Вы можете добавить слушатель в вашем viewDidAppear метода контроллера представления следующим образом:

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

Это позволяет выполнить код, когда состояние аутентификации пользователя изменилось. Он позволяет прослушивать событие, так как метод signOut от Firebase не имеет обработчика завершения.

0

Я только что то, что я думаю, что это та же самая проблема -. Firebase + Swift 3 не вызовет stateDidChangeListeners на выходе из системы, который оставил мое приложение думает пользователь по-прежнему регистрируется в

Что в конечном итоге работает для меня для сохранения и повторного использования отдельной ссылки на экземпляр FIRAuth.auth() вместо вызова FIRAuth.auth() каждый раз.

Вызов FIRAuth.auth()?.signOut() не будет запускать stateDidChangeListeners, который я ранее прилагал. Но когда я сохранил переменную и повторно использовал ее в обоих методах, она работала так, как ожидалось.

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

    } 

} 

Пока вы ссылаетесь текущего пользователя от этой ручки, его будет обновлять текущего пользователя независимо от состояния аутентификации.

0

В некоторых ответах используется разворот силы, когда метод выкидывания базы данных может вызывать ошибку. НЕ ДЕЛАЙ ЭТО!

Вместо вызов должен быть сделан в сделай - поймать - блок, как показано ниже

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

Вы можете слушать изменения состояния с помощью Auth.auth() addStateDidChangeListener и обрабатывать соответствующим образом..

Смежные вопросы