Como obter o controlador de visualização root?


109

Preciso de uma instância do controlador de exibição raiz.

Eu tentei essas abordagens:

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

Retorna: nulo :

Além disso, quando tento obter uma série de controladores:

NSArray *viewControllers = self.navigationController.viewControllers;

Ele retorna apenas um controlador, mas não é meu controlador de visualização raiz.

Se eu tentar tirar do controlador de navegação:

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

Retorna: nulo :

Alguma ideia por quê? O que mais eu poderia tentar obter uma instância do meu controlador de visualização raiz?

Obrigado.


O keyWindow é a janela ativa, por exemplo, quando você mostra um UIAlertView, a janela do UIAlertView é o keyWindow, mas não é a janela do AppDelegate. Se você deseja obter o rootViewController do aplicativo, talvez use [[[UIApplication sharedApplication] delegate] janela] rootViewController ] é melhor.
— 无 夜 之 星辰

Respostas:


213

se você está tentando acessar o rootViewControllerdefinido em seu appDelegate. tente isto:

Objective-C

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

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

Swift 5 e 5.1 e 5.2

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

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

1
No Swift2, você deve usar "let appDelegate = UIApplication.sharedApplication (). Delegate as! AppDelegate", para forçar o desempacotamento
— Jacky

Existe alguma maneira de ter dois controladores atribuídos dessa maneira para que você possa puxar dados de ambos para o relógio?
— Johnny Marin

1
Este é um salva-vidas. Obrigado! Levei meses para encontrar este código delicioso!
— ItsMeDom

37

Objective-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
Esta deve ser a melhor resposta. +1 As outras respostas não funcionarão se você precisar fazer referência ao controlador de visualização raiz de uma estrutura diferente da qual seu aplicativo principal depende.
— C. Tewalt

10

Conforme sugerido aqui por @ 0x7fffffff, se você tiver UINavigationController, pode ser mais fácil de fazer:

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

O código na resposta acima retorna controlador UINavigation (se você o tiver) e se for isso que você precisa, você pode usar self.navigationController.


5

A menos que você tenha um bom motivo, em seu controlador raiz faça o seguinte:

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

E quando você quiser notificá-lo:

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

2

Swift 3

let rootViewController = UIApplication.shared.keyWindow?.rootViewController

1

Maneira rápida de fazer isso, você pode chamar de qualquer lugar, ele retorna opcional, então fique atento a isso:

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

Está incluído como uma função padrão em:

https://github.com/goktugyil/EZSwiftExtensions


1

Swift 3: Mude o ViewController com o Segue Out e envie AnyObject Use: Identidade MainPageViewController no ViewController de destino

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

var mainPageNav = UINavigationController(rootViewController: mainPage)

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

ou se você deseja alterar a visualização do controlador e enviar dados

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)  

Você é o melhor cara :)
— bsm-2000
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.