修复 Firebase 错误的初始 ViewController

Initial ViewController with Firebase bug fix

我有一个奇怪的错误,我不知道如何解决。当我设置应该打开哪个 ViewController 取决于用户是否已注册并且我将这段代码放在 SceneDelegate 中时,我在出现 ViewController

之前黑屏了一会儿
import UIKit
import FirebaseAuth

    class SceneDelegate: UIResponder, UIWindowSceneDelegate {
    
        var window: UIWindow?
        let storyBoard = UIStoryboard(name: "Main", bundle: nil)
    
    
        func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
            guard let windowScene = (scene as? UIWindowScene) else { return }
            window = UIWindow(frame: windowScene.coordinateSpace.bounds)
            window?.windowScene = windowScene
    
            if let user = Auth.auth().currentUser {
                FirestoreService.shared.getUserData(user: user) { (result) in
                    switch result {
                    case .success(let muser):
                        let navigationController = self.storyBoard.instantiateViewController(withIdentifier: "Navigation") as! UINavigationController
                        let conroller = self.storyBoard.instantiateViewController(withIdentifier: "MainController") as! MainController
                        navigationController.viewControllers = [conroller]
                        self.window?.rootViewController = navigationController
                    case .failure(_):
                        let conroller = self.storyBoard.instantiateViewController(withIdentifier: "SignUpController") as! SignUpController
                        self.window?.rootViewController = conroller
                    }
                }
            } else {
                print(3)
                let conroller = storyBoard.instantiateViewController(withIdentifier: "SignUpController") as! SignUpController
                self.window?.rootViewController = conroller
            }
            window?.makeKeyAndVisible()
        }

但是当我将出现 ViewController 的代码放在 firebase 之外时,它可以正常工作。如何解决?

我认为有两种方法可以解决这个问题。

1。使用启动画面:

不要在 scene(_:, session, connectionOptions) 中做出显示登录屏幕或主屏幕的决定。相反,创建一个名为 SplashScreenViewController 的新视图控制器。将应用程序的徽标设置在其中心。然后在其 viewDidLoad() 中移动您的逻辑以检查用户是否已登录:

func chooseAndPresentStartScreen() {
    let storyBoard = UIStoryboard(name: "Main", bundle: nil)
    if let user = Auth.auth().currentUser {
        FirestoreService.shared.getUserData(user: user) { (result) in
            switch result {
            case .success(let muser):
                let navigationController = storyBoard.instantiateViewController(withIdentifier: "Navigation") as! UINavigationController
                let conroller = storyBoard.instantiateViewController(withIdentifier: "MainController") as! MainController
                navigationController.viewControllers = [conroller]
                self.present(navigationController, animated: true, completion: nil)
                
            case .failure(_):
                let conroller = storyBoard.instantiateViewController(withIdentifier: "SignUpController") as! SignUpController
                self.present(conroller, animated: true, completion: nil)
            }
        }
    } else {
        print(3)
        let conroller = storyBoard.instantiateViewController(withIdentifier: "SignUpController") as! SignUpController
        self.present(conroller, animated: true, completion: nil)
    }
}

2。使用用户默认值:

为用于保存用户默认值的键定义一个全局变量。

let isUserLoggedInKey: String = "IsUserLoggedIn"

用户登录后:

let defaults = UserDefaults.standard
defaults.setValue(true, forKey: isUserLoggedInKey)

然后在您的 scene(_:, session, connectionOptions) 中检查是否设置了此值。

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
    guard let windowScene = (scene as? UIWindowScene) else { return }
    window = UIWindow(frame: windowScene.coordinateSpace.bounds)
    window?.windowScene = windowScene
    let defaults = UserDefaults.standard
    let isLoggedIn = defaults.bool(forKey: isUserLoggedInKey)
    if isLoggedIn {
        
        let navigationController = self.storyBoard.instantiateViewController(withIdentifier: "Navigation") as! UINavigationController
        let conroller = self.storyBoard.instantiateViewController(withIdentifier: "MainController") as! MainController
        navigationController.viewControllers = [conroller]
        self.window?.rootViewController = navigationController
        
    } else {
        let conroller = self.storyBoard.instantiateViewController(withIdentifier: "SignUpController") as! SignUpController
        self.window?.rootViewController = conroller
    }
    window?.makeKeyAndVisible()
    
}   

不要忘记在用户注销时将 isLoggedInKey 设置为 false。

let defaults = UserDefaults.standard
defaults.setValue(false, forKey: isUserLoggedInKey)

如果您不想在用户登录和注销时手动保存 isUserLoggedInKey 的值,您还可以使用状态更改侦听器。它需要一个在用户登录或注销时触发的回调。在您的登录视图控制器中添加:

Auth.auth().addStateDidChangeListener { (auth, user) in 
    let defaults = UserDefaults.standard
    defaults.setValue(user != nil, forKey: isUserLoggedInKey)
}