Comment obtenir le contrôleur de vue racine?


109

J'ai besoin d'une instance de contrôleur de vue racine.

J'ai essayé ces approches:

UIViewController *rootViewController = (UIViewController*)[[[UIApplication sharedApplication] keyWindow] rootViewController];

Renvoie: null :

Aussi quand j'essaye d'obtenir un tableau de contrôleurs:

NSArray *viewControllers = self.navigationController.viewControllers;

Il ne renvoie qu'un seul contrôleur, mais ce n'est pas mon contrôleur de vue racine.

Si j'essaye de prendre du contrôleur de navigation:

UIViewController *root = (UIViewController*)[self.navigationController.viewControllers objectAtIndex:0];

Renvoie: null :

Des idées pourquoi? Que puis-je essayer d'autre pour obtenir une instance de mon contrôleur de vue racine?

Merci.


La keyWindow est la fenêtre active, par exemple, lorsque vous affichez un UIAlertView, la fenêtre de UIAlertView est la keyWindow mais ce n'est pas la fenêtre de AppDelegate. ] est mieux.
无 夜 之 星辰

Réponses:


213

si vous essayez d'accéder rootViewControllerau fichier que vous avez défini dans votre appDelegate. essaye ça:

Objectif c

YourViewController *rootController = (YourViewController*)[[(YourAppDelegate*)
                                   [[UIApplication sharedApplication]delegate] window] rootViewController];

Rapide

let appDelegate  = UIApplication.sharedApplication().delegate as AppDelegate
let viewController = appDelegate.window!.rootViewController as YourViewController

Swift 3

let appDelegate  = UIApplication.shared.delegate as! AppDelegate
let viewController = appDelegate.window!.rootViewController as! YourViewController

Swift 4 et 4.2

let viewController = UIApplication.shared.keyWindow!.rootViewController as! YourViewController

Swift 5 et 5.1 et 5.2

let viewController = UIApplication.shared.windows.first!.rootViewController as! YourViewController

3
YourViewController * rootController = (YourViewController *) [[(YourAppDelegate *) [[UIApplication sharedApplication] delegate] window] rootViewController];
Craig Moore

1
Dans Swift2, vous devez utiliser "let appDelegate = UIApplication.sharedApplication (). Delegate as! AppDelegate", pour forcer le déballage
Jacky

Existe-t-il un moyen d'attribuer deux contrôleurs de cette manière afin de pouvoir extraire les données des deux vers la montre?
Johnny Marin

1
C'est une bouée de sauvetage. Je vous remercie! Il m'a fallu des mois pour trouver ce morceau de code délicieux!
ItsMeDom

37

Objectif c

UIViewController *controller = [UIApplication sharedApplication].keyWindow.rootViewController;

Swift 2.0

let viewController = UIApplication.sharedApplication().keyWindow?.rootViewController

Swift 5

let viewController = UIApplication.shared.keyWindow?.rootViewController

3
Cela devrait être la meilleure réponse. +1 Les autres réponses ne fonctionneront pas si vous devez référencer le contrôleur de vue racine à partir d'un autre framework dont dépend votre application principale.
C.Tewalt

10

Comme suggéré ici par @ 0x7fffffff, si vous avez UINavigationController, cela peut être plus facile à faire:

YourViewController *rootController =
    (YourViewController *)
        [self.navigationController.viewControllers objectAtIndex: 0];

Le code dans la réponse ci-dessus renvoie le contrôleur UINavigation (si vous l'avez) et si c'est ce dont vous avez besoin, vous pouvez l'utiliser self.navigationController.


5

Sauf si vous avez une bonne raison, dans votre contrôleur racine, procédez comme suit:

[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(onTheEvent:)
                                             name:@"ABCMyEvent"
                                           object:nil];

Et lorsque vous souhaitez le notifier:

[[NSNotificationCenter defaultCenter] postNotificationName:@"ABCMyEvent"
                                                object:self];                

2

Swift 3

let rootViewController = UIApplication.shared.keyWindow?.rootViewController

1

Façon rapide de le faire, vous pouvez l'appeler de n'importe où, cela retourne facultatif, alors faites attention à cela:

/// EZSwiftExtensions - Gives you the VC on top so you can easily push your popups
var topMostVC: UIViewController? {
    var presentedVC = UIApplication.sharedApplication().keyWindow?.rootViewController
    while let pVC = presentedVC?.presentedViewController {
        presentedVC = pVC
    }

    if presentedVC == nil {
        print("EZSwiftExtensions Error: You don't have any views set. You may be calling them in viewDidLoad. Try viewDidAppear instead.")
    }
    return presentedVC
}

Il est inclus en tant que fonction standard dans:

https://github.com/goktugyil/EZSwiftExtensions


1

Swift 3: Chage ViewController withOut Segue et envoie AnyObject Utilisation: Identity MainPageViewController sur le ViewController cible

let mainPage = self.storyboard?.instantiateViewController(withIdentifier: "MainPageViewController") as! MainPageViewController

var mainPageNav = UINavigationController(rootViewController: mainPage)

self.present(mainPageNav, animated: true, completion: nil)

ou si vous souhaitez changer de contrôleur de vue et envoyer des données

let mainPage = self.storyboard?.instantiateViewController(withIdentifier: "MainPageViewController") as! MainPageViewController

let dataToSend = "**Any String**" or  var ObjectToSend:**AnyObject** 

mainPage.getData = dataToSend 

var mainPageNav = UINavigationController(rootViewController: mainPage)

self.present(mainPageNav, animated: true, completion: nil)  

Vous êtes le meilleur mec :)
bsm-2000
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.