Swift: представлены два контроллера представления - PullRequest
0 голосов
/ 20 июня 2020

Извинения за двусмысленность вопроса; Я постараюсь пояснить здесь более ясную картину.

Проблема

У меня есть код в AppDelegate.swift, который выполняет условную навигацию; если пользователь вошел в систему (и, следовательно, currentUser не nil), приложение запустится в View, контроллере представления в раскадровке Main. В противном случае, если пользователь не вошел в систему, приложение запустится в Welcome, контроллере представления в Auth раскадровке.

Ниже приведен мой код из AppDelegate.swift, ViewController.swift ( который равен View) и WelcomeViewController.

Примечание:

View - это идентификатор раскадровки, который я установил для ViewController; Welcome - это идентификатор раскадровки, который я установил для WelcomeViewController.

AppDelegate.swift

import UIKit
import Firebase

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?

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

        // Configures the Firebase library.
        FirebaseApp.configure()

        // Performs conditional navigation on the condition of currentUser's status.
        self.window = UIWindow(frame: UIScreen.main.bounds)
        let user = Auth.auth().currentUser
        if user != nil {
            let storyboard = UIStoryboard(name: "Main", bundle: nil)
            let rootViewController = storyboard.instantiateViewController(identifier: "View")
            window?.rootViewController = rootViewController
            UIView.animate(withDuration: 0.5) {
                self.window?.makeKeyAndVisible()
            }
        } else {
            let storyboard = UIStoryboard(name: "Auth", bundle: nil)
            let rootViewController = storyboard.instantiateViewController(identifier: "Welcome")
            window?.rootViewController = rootViewController
            UIView.animate(withDuration: 0.5) {
                self.window?.makeKeyAndVisible()
            }
        }

        return true
    }

}

ViewController.swift

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
        print("ViewController presented.")
    }

}

WelcomeViewController.swift

import UIKit

class WelcomeViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
        print("WelcomeViewController presented.")
    }

}

Ожидания

Приложение свежеустановлено на Симуляторе, а значит, currentUser быть не должно (и при отладке подтверждается). Поэтому я ожидал увидеть это как вывод в консоли:

WelcomeViewController presented.

Вместо этого это отображается в консоли:

WelcomeViewController presented.
ViewController presented.

Попытки

До сих пор я думал, что проблема могла возникнуть из-за того, что раскадровка Main является раскадровкой по умолчанию, установленной с момента создания проекта. Поэтому я попытался снять флажок «Контроллер начального представления» для двух контроллеров представления. Как я и ожидал, вместо него появляется следующее:

WelcomeViewController presented.
2020-06-20 11:39:38.724658+0800 AppName[11439:237509] [WindowScene] Failed to instantiate the default view controller for UIMainStoryboardFile 'Main' - perhaps the designated entry point is not set?

Что мне делать, чтобы убедиться, что ViewController не появляется, а заменить WelcomeViewController? Любая помощь приветствуется, спасибо!

Ответы [ 2 ]

1 голос
/ 20 июня 2020

почему бы не установить WelcomeViewController в качестве «Начального контроллера представления» и заменить его код viewDidLoad файлом AppDelegate, тогда:

class WelcomeViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
        print("WelcomeViewController presented.")

        let user = Auth.auth().currentUser
        if user != nil {
            let storyboard = UIStoryboard(name: "Main", bundle: nil)
            let rootViewController = storyboard.instantiateViewController(identifier: "View")
            window?.rootViewController = rootViewController
            UIView.animate(withDuration: 0.5) {
                self.window?.makeKeyAndVisible()
            }
        } 
    }

}

вы также можете посмотреть это, если хотите установить контроллер представления из AppDelegate:

EDIT: вы можете использовать UINavigationController в качестве исходного контроллера представления, как указано в этом ответе:

установить начальный контроллер представления в appdelegate - swift тогда вам просто нужно установите правильный контроллер представления здесь:

navigationController.viewControllers = [rootViewController]
self.window?.rootViewController = navigationController
0 голосов
/ 20 июня 2020

Решение

Мне удалось найти решение проблемы, с которой я столкнулся здесь. В коде есть две ошибки, указанные выше, и я объясню их здесь:

Ошибка 1: Код должен быть в SceneDelegate вместо AppDelegate (iOS 13)

Xcode 11, наряду с выпуском iOS 13, представил SceneDelegate.swift. Я должен был поместить свой код выше в SceneDelegate.swift вместо AppDelegate.swift; поскольку я этого не делал, код не работал так, как я ожидал, для моего симулятора, который работал iOS 13.5.

Вот мой исправленный код в SceneDelegate.swift:

import UIKit
import Firebase

class SceneDelegate: UIResponder, UIWindowSceneDelegate {

    var window: UIWindow?

    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
        // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
        // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
        guard let _ = (scene as? UIWindowScene) else { return }

        // Performs conditional navigation on the condition of currentUser's status.
        let user = Auth.auth().currentUser
        if user != nil {
            let storyboard = UIStoryboard(name: "Main", bundle: nil)
            let rootViewController = storyboard.instantiateViewController(identifier: "View")
            window?.rootViewController = rootViewController
            UIView.animate(withDuration: 0.5) {
                self.window?.makeKeyAndVisible()
            }
        } else {
            let storyboard = UIStoryboard(name: "Auth", bundle: nil)
            let rootViewController = storyboard.instantiateViewController(identifier: "Welcome")
            window?.rootViewController = rootViewController
            UIView.animate(withDuration: 0.5) {
                self.window?.makeKeyAndVisible()
            }
        }
    }

}

Ошибка 2 (Важно!): Определение нового UIWindow

В моем приведенном выше коде была неправильная строка, которая привела к созданию нового UIWindow:

self.window = UIWindow(frame: UIScreen.main.bounds)

Удалив эту строку кода, проблема была решена. Вот исправленный код:

let user = Auth.auth().currentUser
if user != nil {
    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    let rootViewController = storyboard.instantiateViewController(identifier: "View")
    window?.rootViewController = rootViewController
    UIView.animate(withDuration: 0.5) {
        self.window?.makeKeyAndVisible()
    }
} else {
    let storyboard = UIStoryboard(name: "Auth", bundle: nil)
    let rootViewController = storyboard.instantiateViewController(identifier: "Welcome")
    window?.rootViewController = rootViewController
    UIView.animate(withDuration: 0.5) {
        self.window?.makeKeyAndVisible()
    }
}

Надеюсь, это поможет всем, кто сталкивается с этой проблемой!

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