使用 Firebase 身份验证 Xcode 保持登录状态

时间:2020-12-25 04:39:14

标签: ios swift firebase firebase-authentication

我有一个已连接到 Firebase 并具有电子邮件/密码登录名的应用。但是,当我登录应用程序并关闭应用程序时,它不会保持登录状态。我尝试了其他线程中的一些操作(其中一个在我当前的代码中),但没有一个成功.任何帮助,谢谢!

登录电子邮件视图控制器:

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 内。单击“退出”后,将返回欢迎屏幕。

2 个答案:

答案 0 :(得分:0)

Firebase 会在应用重新加载时自动恢复用户的身份验证状态。这是一个异步操作,因为它需要调用服务器,因此需要设置您的代码来处理此问题。

因此,如果您现在调用 signIn(withEmail: , password: ) 来处理活动登录,您还需要调用以 addStateDidChangeListener 的形式处理身份验证状态的恢复。来自 determining the currently signed in user 的文档中有这个例子:

handle = Auth.auth().addStateDidChangeListener { (auth, user) in
  // ...
}

如果您在应用程序启动时附加此侦听器,当 Firebase 客户端开始恢复状态时,它最初会以 null 为用户调用,然后一旦状态恢复,它将以实际触发用户对象。

在此回调中,您可以将用户分派到正确的屏幕以处理他们的状态。

答案 1 :(得分:0)

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

这可以无缝运行,而且非常简单!