Контроллер представления не инстанцирует внутри оператора IF - PullRequest
0 голосов
/ 27 октября 2018

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

В моем примере, если пользователь является «драйвером», то есть значение в firebase равно «true», тогда я хочу, чтобы они перешли к контроллеру представления «Driver». Если пользователь НЕ является «драйвером», то я хочу, чтобы он перешел к контроллеру представления «Пользователь» (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 голосов
/ 27 октября 2018

Я не использовал FireBase, но метод, который вы используете, observeSingleEvent(of:with:) почти наверняка является асинхронным событием. Возвращается немедленно, прежде чем чтение базы данных будет завершено. Вы передаете замыкание (блок кода), и вызов выполняет этот код после завершения выборки.

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

Таким образом, вы не можете делать то, что пытаетесь сделать. Ваша переменная rootVC будет равна нулю, когда вы попадете в код appDelegate после блока if / else.

Вам нужно найти другой способ сделать то, что вы делаете.

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

EDIT:

Создать контроллер представления. Назовите это ContainerViewController. Установите его в качестве корневого контроллера просмотра окна при запуске. Дайте этому контроллеру представление контейнера. Настройте viewDidLoad() контроллера этого представления для вызова вызова firebase, и в обработчике завершения вызова firebase решите, какой тип контроллера представления создать, и установите этот контроллер представления в представлении контейнера.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...