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.