Оставайтесь в системе с Firebase Authentication Xcode

У меня есть приложение, которое уже подключено к 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. Когда нажимается «выйти», он возвращается к экрану приветствия.

Можете ли вы объяснить, как вы определяете, что «он не остается в системе»? Итак: из кода, которым вы поделились, если вы пройдете его в отладчике, какая строка не делает то, что вы ожидаете?

Frank van Puffelen 25.12.2020 05:57

@FrankvanPuffelen Когда я нажимаю «Войти», в отладчике отображается, что вход выполнен успешно. Когда я нажимаю «Выйти», в отладчике отображается, что выход из системы выполнен успешно. Однако, когда я выхожу из приложения (закрываю приложение), даже если я ранее вошел в систему и был в ProfileViewController, я автоматически возвращаюсь в WelcomeViewController. Я хочу, чтобы он оставался в системе и превосходил экран приветствия / входа, если я закрыл приложение во время входа в систему. Я также хочу, чтобы он оставался в системе, если я закрыл приложение во время выхода из системы.

user11628649 25.12.2020 06:59

Если вы хотите оставаться в системе, не выходите из нее по телефону signOut(). Это удалит все, что SDK знает о пользователе.

Doug Stevenson 25.12.2020 07:55

@DougStevenson, у пользователя есть кнопка для выхода. вот почему есть signOut(), когда они нажимают на нее. таким образом, они останутся в системе, если они нажмут на нее. Моя проблема остается подписанным IN.

user11628649 25.12.2020 18:19

Если пользователь выразил желание выйти из системы, почему вы хотите, чтобы он оставался в системе? Пусть пользователь сам решает, чего он хочет.

Doug Stevenson 25.12.2020 18:57

Я уже решил свою проблему с помощью @FrankvanPuffelen. Я не думаю, что вы поняли мою проблему. Я хотел, чтобы пользователь вошел в систему, если он ранее вошел в систему, даже если он закрыл приложение, и чтобы он оставался вне системы, в которой он ранее вышел, даже если они закрыли приложение. Раньше я не мог оставить пользователя в системе, если он вошел в систему (или, другими словами, они оставались в системе, когда закрывали приложение, независимо от того, входили ли они ранее)

user11628649 25.12.2020 20:08
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
6
315
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

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

Итак, теперь, когда у вас есть вызов signIn(withEmail: , password: ) для обработки активного входа, вам также понадобится вызов для обработки восстановления состояния аутентификации в форме addStateDidChangeListener. Из документации по определению текущего пользователя, вошедшего в систему, можно привести следующий пример:

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

Если вы прикрепите этот прослушиватель при запуске приложения, он сначала будет вызываться с null для пользователя, поскольку клиент Firebase начнет восстанавливать состояние, а затем, как только состояние будет восстановлено, он сработает с фактическим объектом пользователя.

В этом обратном вызове вы можете отправить пользователя на правильный экран, чтобы обработать его состояние.

мне нужно только добавить его в контроллер представления входа в систему или вместо этого он должен быть в контроллере представления приветствия? Будет ли это в функции viewDidLoad? Кроме того, можете ли вы показать мне, как я должен реализовать это в своем коде?

user11628649 25.12.2020 18:12

Этот код нужен везде, где нужно отслеживать статус аутентификации пользователя. На самом деле не имеет значения, в какой VC вы его поместите, но вы будете использовать его там, чтобы затем потенциально перенаправить пользователя на другой VC на основе их состояния аутентификации.

Frank van Puffelen 25.12.2020 18:49

это сработало! Спасибо большое, вы спасаете!

user11628649 25.12.2020 20:02

С помощью @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")
            
          }
        }

Это работало без проблем и очень просто!

Другие вопросы по теме