¿Cómo obtener el controlador de vista raíz?

109

Necesito una instancia del controlador de vista raíz.

Probé esos enfoques:

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

Devoluciones: nulo :

Además, cuando trato de obtener una matriz de controladores:

NSArray *viewControllers = self.navigationController.viewControllers;

Devuelve solo un controlador, pero no es mi controlador de vista raíz.

Si trato de tomar del controlador de navegación:

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

Devoluciones: nulo :

¿Alguna idea de por qué? ¿Qué más puedo intentar para obtener una instancia de mi controlador de vista raíz?

Gracias.

Niño de la calle
fuente
KeyWindow es la ventana activa, por ejemplo, cuando muestra un UIAlertView, la ventana de UIAlertView es keyWindow pero no es la ventana de AppDelegate. Si desea obtener el rootViewController de la aplicación, tal vez use [[[UIApplication sharedApplication] delegate] window] rootViewController ] es mejor.
无 夜 之 星辰

Respuestas:

213

si está intentando acceder al rootViewControllerque configuró en su appDelegate. prueba esto:

C objetivo

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

Rápido

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 y 4.2

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

Swift 5 y 5.1 y 5.2

let viewController = UIApplication.shared.windows.first!.rootViewController as! YourViewController
Janusfidel
fuente
3
YourViewController * rootController = (YourViewController *) [[(YourAppDelegate *) [[UIApplication sharedApplication] delegado] ventana] rootViewController];
Craig Moore
1
En Swift2, tienes que usar "let appDelegate = UIApplication.sharedApplication (). Delegate as! AppDelegate", para forzar el desenvolvimiento
Jacky
¿Hay alguna forma de tener dos controladores asignados de esta manera para que pueda extraer datos de ambos al reloj?
Johnny Marin
1
Este es un salvavidas. ¡Gracias! ¡Me tomó meses encontrar este delicioso código!
ItsMeDom
37

C objetivo

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

Swift 2.0

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

Rápido 5

let viewController = UIApplication.shared.keyWindow?.rootViewController
Chamath Jeevan
fuente
3
Esta debería ser la mejor respuesta. +1 Las otras respuestas no funcionarán si necesita hacer referencia al controlador de vista raíz desde un marco diferente del que depende su aplicación principal.
C. Tewalt
10

Como lo sugiere aquí @ 0x7fffffff, si tiene UINavigationController, puede ser más fácil de hacer:

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

El código en la respuesta anterior devuelve el controlador UINavigation (si lo tiene) y si esto es lo que necesita, puede usarlo self.navigationController.

esp
fuente
5

A menos que tenga una buena razón, en su controlador raíz haga esto:

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

Y cuando quieras notificarlo:

[[NSNotificationCenter defaultCenter] postNotificationName:@"ABCMyEvent"
                                                object:self];                
nostálgico
fuente
2

Swift 3

let rootViewController = UIApplication.shared.keyWindow?.rootViewController
cybermach
fuente
1

Una forma rápida de hacerlo, puede llamar a esto desde cualquier lugar, devuelve opcional, así que tenga cuidado con eso:

/// 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
}

Se incluye como función estándar en:

https://github.com/goktugyil/EZSwiftExtensions

Esqarrouth
fuente
1

Swift 3: Chage ViewController con Out Segue y envía AnyObject Use: Identity MainPageViewController en el ViewController de destino

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

var mainPageNav = UINavigationController(rootViewController: mainPage)

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

o si desea cambiar el controlador de vista y enviar datos

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)  
usuario6857463
fuente
Eres el mejor amigo :)
bsm-2000