9 votes

Définir rootViewController iOS 13

Après avoir mis à jour Xcode, une partie critique de mon application a cessé de fonctionner.

Lorsque mon application se lance, j'exécute une fonction pour vérifier des drapeaux booléens et définir le rootViewController correct.

Mais le code que j'utilise pour le définir a maintenant cessé de fonctionner

class func setLoginAsInitialViewContoller(window:UIWindow) {
    print("SET LOGIN") 
    let storyboard = UIStoryboard(name: "Login", bundle: nil)
    let controller = storyboard.instantiateViewController(withIdentifier: "LoginViewController")
    controller.modalPresentationStyle = .overFullScreen
    window.rootViewController = controller
    window.makeKeyAndVisible()
}

Plus précisément, lorsque l'application arrive à l'avant-dernière ligne window.rootViewController = controller, elle plante avec une erreur libc++abi.dylib: terminating with uncaught exception of type NSException.

La fonction ci-dessus se trouve dans une classe appelée Utilities.swift et j'appelle la fonction depuis mon AppDelegate.swift comme indiqué ci-dessous:

class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?
    var storyboard: UIStoryboard? = nil

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

        UIApplication.shared.isIdleTimerDisabled = true
        Utilities.decideInitialViewController(window: self.window!)

        return true
    }

Toute solution ou correction sur comment je peux définir le contrôleur racine est grandement appréciée.

Merci!

13voto

lacefarin Points 860

Cela est dû au fait que l'AppDelegate n'a plus de propriété window. Maintenant, vous devez utiliser la méthode scene(_:willConnectTo:options:) de SceneDelegate pour changer le contrôleur de vue racine. Comme indiqué dans cet exemple :

    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        guard let scene = (scene as? UIWindowScene) else { return }

        // Instancier UIWindow avec la scène
        let window = UIWindow(windowScene: scene)
        // Assigner la fenêtre à la propriété window de SceneDelegate
        self.window = window
        // Définir le contrôleur de vue initial du storyboard principal comme contrôleur de vue racine de UIWindow
        self.window?.rootViewController = UIStoryboard(name: "Main", bundle: nil).instantiateInitialViewController()
        // Présenter la fenêtre à l'écran
        self.window?.makeKeyAndVisible()
    }

7voto

Nidhi Points 109

Il est disponible dans le fichier SceneDelegate.swift de votre projet

Il aura la méthode déléguée :

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions)

Exemple

func scene(_ scene: UIScene, willConnectTo session: UISceneSession,
 options connectionOptions: UIScene.ConnectionOptions) {

if let windowScene = scene as? UIWindowScene {

    self.window = UIWindow(windowScene: windowScene) 

    let initialViewController = 
        storyboard.instantiateViewController(withIdentifier: "FirstViewController")            
        self.window!.rootViewController = initialViewController
        self.window!.makeKeyAndVisible()
    }

}

5voto

dinesh sharma Points 399

Dans viewDidAppear vous pouvez définir root:-

  override func viewDidAppear(_ animated: Bool) {
            print(self.view.window)
            let vc = self.storyboard?.instantiateViewController(identifier: "SecondViewController") as? SecondViewController
            self.view.window?.rootViewController = vc
        }

0voto

RongyanZheng Points 129
  • Si vous voulez utiliser ScenceDelegate. Dans scene(_:willConnectTo:options:, crée une nouvelle UIWindow, définit le rootViewController de la fenêtre et fait de cette fenêtre la fenêtre key.
  • Si vous ne voulez pas utiliser ScenceDelegate, vous pouvez essayer de le supprimer en suivant ceci.

0voto

Larry Mickie Points 101

Pour toute personne souhaitant créer quelques extensions pour changer le contrôleur de vue racine et ayant besoin de prendre en charge les deux types de délégués (UISceneDelegate et AppDelegate), voici quelques exemples :

    extension UIViewController {
        var appDelegate: AppDelegate {
        return UIApplication.shared.delegate as! AppDelegate
    }

    var sceneDelegate: SceneDelegate? {
        guard let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
            let delegate = windowScene.delegate as? SceneDelegate else { return nil }
         return delegate
    }
}

Et si vous avez besoin d'une extension pour accéder à la UIWindow depuis un ViewController avec prise en charge d'iOS12 et d'iOS13 :

extension UIViewController {

    var window: UIWindow? {
        if #available(iOS 13, *) {
            guard let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
                let delegate = windowScene.delegate as? SceneDelegate, let window = delegate.window else { return nil }
                   return window
        }

        guard let delegate = UIApplication.shared.delegate as? AppDelegate, let window = delegate.window else { return nil }
        return window
    }
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X