У меня есть приложение, которое уже подключено к Firebase и имеет логин по электронной почте/паролю. Однако, когда я вхожу в приложение и закрываю приложение, оно не остается в системе. Я пробовал несколько вещей из других потоков (один из которых находится внутри моего текущего кода), но ни один из них не увенчался успехом. . Что-нибудь поможет, спасибо!
ЛогинEmailViewController:
import UIKit
import FirebaseAuth
class LoginEmailViewController: UIViewController {
let userDefault = UserDefaults.standard
let launchedBefore = UserDefaults.standard.bool(forKey: "isLoggedIn")
@IBOutlet weak var loginEmailTextField: UITextField!
@IBOutlet weak var loginPasswordTextField: UITextField!
@IBOutlet weak var loginButton: UIButton!
@IBOutlet weak var loginErrorLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
setUpElements()
}
func setUpElements() {
// hide error label
loginErrorLabel.alpha = 0
// style the textfields
Utilities.styleTextField(loginEmailTextField)
Utilities.styleTextField(loginPasswordTextField)
}
@IBAction func loginTapped(_ sender: Any) {
// TODO: Validate Text Fields
// Create cleaned versions of the text field
let email = loginEmailTextField.text!.trimmingCharacters(in: .whitespacesAndNewlines)
let password = loginPasswordTextField.text!.trimmingCharacters(in: .whitespacesAndNewlines)
// Signing in the user
Auth.auth().signIn(withEmail: email, password: password) { (result, error) in
if error != nil {
// Couldn't sign in
self.loginErrorLabel.text = error!.localizedDescription
self.loginErrorLabel.alpha = 1
}
else {
// user signed in successfully, perform segue to tableViewController and set userDefault to true
print("User signed in")
self.userDefault.set(true, forKey: "isLoggedIn")
self.userDefault.synchronize()
let vc = UITableViewController()
vc.modalPresentationStyle = .fullScreen
self.performSegue(withIdentifier: "signInSegue", sender: nil)
self.present(vc, animated: true)
}
}
}
}
Профилвиевконтроллер:
import UIKit
import FirebaseAuth
class ProfileViewController: UIViewController {
let userDefault = UserDefaults.standard
let launchedBefore = UserDefaults.standard.bool(forKey: "isLoggedIn")
@IBOutlet var tableView: UITableView!
let data = ["Sign Out"]
override func viewDidLoad() {
super.viewDidLoad()
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
tableView.delegate = self
tableView.dataSource = self
view.backgroundColor = .blue
}
}
extension ProfileViewController: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return data.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = data[indexPath.row]
cell.textLabel?.textAlignment = .center
cell.textLabel?.textColor = .red
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
let signOutAction = UIAlertAction(title: "Sign Out", style: .destructive) { (action) in
do {
try FirebaseAuth.Auth.auth().signOut()
// switch screen to welcome screen
self.userDefault.set(false, forKey: "isLoggedIn")
self.userDefault.synchronize()
let vc = WelcomeViewController()
vc.modalPresentationStyle = .fullScreen
self.performSegue(withIdentifier: "logOutSegue", sender: nil)
self.present(vc, animated: true)
print("Successfully logged out")
} catch let err {
print("Failed to log out", err)
Service.showAlert(on: self, style: .alert, title: "Sign Out Error", message: err.localizedDescription)
}
}
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
Service.showAlert(on: self, style: .actionSheet, title: nil, message: nil, actions: [signOutAction, cancelAction], completion: nil)
}
}
Добро пожаловатьВиевконтроллер:
import UIKit
class WelcomeViewController: UIViewController {
let userDefault = UserDefaults.standard
let launchedBefore = UserDefaults.standard.bool(forKey: "isLoggedIn")
@IBOutlet weak var signInFacebookButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
// if user is already signed in, go to tabBarController screens
if userDefault.bool(forKey: "isLoggedIn") {
performSegue(withIdentifier: "currentUserSegue", sender: self)
return
}
setUpElements()
}
func setUpElements() {
let button = signInFacebookButton
button?.layer.borderWidth = 2
button?.layer.borderColor = UIColor.init(red: 93/255, green: 129/255, blue: 140/255, alpha: 1).cgColor
button?.layer.cornerRadius = 20.0
button?.tintColor = UIColor.black
}
}
Кнопка «Выйти» находится внутри ProfileViewController
, а кнопка «Войти» — внутри LoginEmailViewController
. Когда нажимается «выйти», он возвращается к экрану приветствия.
@FrankvanPuffelen Когда я нажимаю «Войти», в отладчике отображается, что вход выполнен успешно. Когда я нажимаю «Выйти», в отладчике отображается, что выход из системы выполнен успешно. Однако, когда я выхожу из приложения (закрываю приложение), даже если я ранее вошел в систему и был в ProfileViewController
, я автоматически возвращаюсь в WelcomeViewController
. Я хочу, чтобы он оставался в системе и превосходил экран приветствия / входа, если я закрыл приложение во время входа в систему. Я также хочу, чтобы он оставался в системе, если я закрыл приложение во время выхода из системы.
Если вы хотите оставаться в системе, не выходите из нее по телефону signOut()
. Это удалит все, что SDK знает о пользователе.
@DougStevenson, у пользователя есть кнопка для выхода. вот почему есть signOut()
, когда они нажимают на нее. таким образом, они останутся в системе, если они нажмут на нее. Моя проблема остается подписанным IN.
Если пользователь выразил желание выйти из системы, почему вы хотите, чтобы он оставался в системе? Пусть пользователь сам решает, чего он хочет.
Я уже решил свою проблему с помощью @FrankvanPuffelen. Я не думаю, что вы поняли мою проблему. Я хотел, чтобы пользователь вошел в систему, если он ранее вошел в систему, даже если он закрыл приложение, и чтобы он оставался вне системы, в которой он ранее вышел, даже если они закрыли приложение. Раньше я не мог оставить пользователя в системе, если он вошел в систему (или, другими словами, они оставались в системе, когда закрывали приложение, независимо от того, входили ли они ранее)
Firebase автоматически восстанавливает состояние аутентификации пользователя при перезагрузке приложения. Это асинхронная операция, так как она требует обращения к серверу, поэтому ваш код должен быть настроен для ее обработки.
Итак, теперь, когда у вас есть вызов signIn(withEmail: , password: )
для обработки активного входа, вам также понадобится вызов для обработки восстановления состояния аутентификации в форме addStateDidChangeListener
. Из документации по определению текущего пользователя, вошедшего в систему, можно привести следующий пример:
handle = Auth.auth().addStateDidChangeListener { (auth, user) in
// ...
}
Если вы прикрепите этот прослушиватель при запуске приложения, он сначала будет вызываться с null
для пользователя, поскольку клиент Firebase начнет восстанавливать состояние, а затем, как только состояние будет восстановлено, он сработает с фактическим объектом пользователя.
В этом обратном вызове вы можете отправить пользователя на правильный экран, чтобы обработать его состояние.
мне нужно только добавить его в контроллер представления входа в систему или вместо этого он должен быть в контроллере представления приветствия? Будет ли это в функции viewDidLoad? Кроме того, можете ли вы показать мне, как я должен реализовать это в своем коде?
Этот код нужен везде, где нужно отслеживать статус аутентификации пользователя. На самом деле не имеет значения, в какой VC вы его поместите, но вы будете использовать его там, чтобы затем потенциально перенаправить пользователя на другой VC на основе их состояния аутентификации.
это сработало! Спасибо большое, вы спасаете!
С помощью @FrankVanPuffelen я только что добавил это в свой MainNavigationController
:
// if user is already signed in, go to tabBarController screens
Auth.auth().addStateDidChangeListener { auth, user in
if user != nil {
// User is signed in. Show home screen
let tabBarC = self.storyboard?.instantiateViewController(withIdentifier: "mainTabBarController") as! TabBarController
tabBarC.modalPresentationStyle = .fullScreen
self.present(tabBarC, animated: false, completion: nil)
print("User signed in, switched to TabBarController")
} else {
// No User is signed in. Show user the login screen
let welcomeVC = self.storyboard?.instantiateViewController(withIdentifier: "welcomeViewController") as! WelcomeViewController
welcomeVC.modalPresentationStyle = .fullScreen
self.present(welcomeVC, animated: false, completion: nil)
print("No user signed in, switched to WelcomeViewController")
}
}
Это работало без проблем и очень просто!
Можете ли вы объяснить, как вы определяете, что «он не остается в системе»? Итак: из кода, которым вы поделились, если вы пройдете его в отладчике, какая строка не делает то, что вы ожидаете?