swift - View Controller 未在 IF 语句中实例化

标签 swift firebase firebase-realtime-database viewcontroller

我正在设计一个应用程序,当用户首次打开它并且他们当前已登录时,我希望它为其数据拍摄快照,然后根据条件实例化一个 View Controller 。

在我的示例中,如果用户是“司机”,意味着 firebase 中的值为“true”,那么我希望他们转到“司机” View Controller 。如果用户不是“驱动程序”,那么我希望他们转到“用户” View Controller (TabBarVC)。如果用户为 nil 或未登录,则他们转到登录 VC。

我已经在没有条件的情况下测试了代码。如果用户已登录(无快照),则转到 TabBarVC,如果用户已注销,则转到 Login VC。

当在这种情况下运行应用程序时,应用程序崩溃并显示“应用程序窗口应该在应用程序启动结束时有一个 Root View Controller ”,这对我来说意味着它没有读取我的使用来自 FireBase 快照的条件时的代码。

请告诉我我做错了什么,我认为“rootVC”可以工作,因为它是一个“var rootVC : UIViewController?”形式的变量

这里是 switcher.swift

import Foundation
import UIKit
import Firebase
import FirebaseAuth
import FirebaseDatabase

class Switcher {
    static func updateRootVC() {

        var rootVC : UIViewController?

        let currentUser = Auth.auth().currentUser?.uid

        if Auth.auth().currentUser != nil{
            DataService.instance.REF_USERS.child(currentUser!).observeSingleEvent(of: .value, with: { (snapshot) in
                if let userSnapshot = snapshot.children.allObjects as? [DataSnapshot] {
                    for user in userSnapshot {
                            if user.childSnapshot(forPath: "driver_profile/is_userdriver").value as? Bool == false {
                                rootVC = UIStoryboard(name: "Driver", bundle: nil).instantiateViewController(withIdentifier: "DriverHomeVC") as! DriverHomeVC
                            } else {
                                rootVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "TabBarVC")
                                return
                        }
                    }
                }
            })
         // rootVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "TabBarVC")
         // rootVC = UIStoryboard(name: "Driver", bundle: nil).instantiateViewController(withIdentifier: "DriverHomeVC") as! DriverHomeVC

        }else{
            rootVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "LoginVC") as! LoginVC

        }

        let appDelegate = UIApplication.shared.delegate as! AppDelegate
        appDelegate.window?.rootViewController = rootVC

    }
}

这是 AppDelegate.swift 的一部分,您需要了解它是如何调用的:

import UIKit
import Firebase
import FirebaseAuth
import FirebaseDatabase
import FirebaseInstanceID


@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    override init() {

        FirebaseApp.configure()
        Database.database().isPersistenceEnabled = true
    }

    var window: UIWindow?


    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {



        Switcher.updateRootVC()

        return true
    }

最佳答案

我没有使用过 FireBase,但是您使用的方法 observeSingleEvent(of:with:) 几乎可以肯定是一个异步事件。它在数据库读取完成之前立即返回。您传入一个闭包(一段代码),并在获取完成后调用运行该代码。

通过异步调用,您传入的代码将永远不会运行,直到函数调用返回,您才能继续应用中的下一步。

因此你不能做你想做的事。当您在 if/else block 之后到达 appDelegate 代码时,您的 rootVC 变量将为 nil。

你需要找到一种不同的方式来做你正在做的事情。

我建议创建一个在所有情况下都是相同类型的 Root View Controller ,并为其提供一个容器 View ,一旦数据库获取完成,它就会加载适当类型的 subview 。

编辑:

创建一个 View Controller 。称它为 ContainerViewController。在启动时将其安装为窗口的 Root View Controller 。给那个 View Controller 一个容器 View 。设置该 View Controller 的 viewDidLoad() 以调用 firebase 调用,并在 firebase 调用的完成处理程序中,决定要实例化的 View Controller 类型,并将该 View Controller 安装在容器 View 中。

关于swift - View Controller 未在 IF 语句中实例化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53025528/

相关文章:

swift - 在 Swift 中更改 UIProgressView 的高度

由方法上下文定义的 Swift 泛型类型

ios - UI 中显示的单元格数量小于数据计数

java - 如何将数据从firebase数据库传递到短信?

android - 如何设置添加 child 时调用的onChildAdded

ios - UIView 与标签栏元素 iOS 重叠

angularjs - 如何在 AWS S3 上上传多个文件并使用 Angular 将 url 存储到 Firebase?

android - 当我尝试上传新的时,我的 firebase 功能被删除了

java - 如何从相机捕获图像并上传到 Firebase

android - firebase 函数中的 initializeApp() 问题