View Controller未在IF语句中实例化

时间:2018-10-27 19:26:03

标签: swift firebase firebase-realtime-database viewcontroller

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

在我的示例中,如果用户是“驱动程序”,则表示Firebase中的值为“ true”,那么我希望他们转到“驱动程序”视图控制器。如果用户不是“驱动程序”,那么我希望他们转到“用户”视图控制器(TabBarVC)。如果用户为nil或未登录,则他们将转到登录VC。

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

在有条件的情况下运行应用程序时,应用程序崩溃并显示“在应用程序启动结束时,应用程序窗口应具有根视图控制器” 对我来说,这意味着它没有读取我的使用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
    }

1 个答案:

答案 0 :(得分:1)

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

使用异步调用,在函数调用返回之前,您传入的代码将永远不会运行,然后继续执行应用程序中的下一步。

因此您无法做您想做的事情。在if / else块之后,进入appDelegate代码时,您的rootVC变量将为nil。

您需要找到其他方式来做自己的事情。

我建议创建一个在所有情况下都具有相同类型的根视图控制器,并为它提供一个容器视图,一旦数据库提取完成,该容器视图就会加载适当类型的子视图。

编辑:

创建一个视图控制器。称之为ContainerViewController。在启动时将其安装为窗口的根视图控制器。给该视图控制器一个容器视图。设置该视图控制器的viewDidLoad()来调用firebase调用,然后在firebase调用的完成处理程序中,确定要实例化哪种类型的视图控制器,并将该视图控制器安装在容器视图中。