Jak zdobyć główny kontroler widoku?

109

Potrzebuję wystąpienia głównego kontrolera widoku.

Wypróbowałem te podejścia:

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

Zwroty: null :

Również gdy próbuję zdobyć tablicę kontrolerów:

NSArray *viewControllers = self.navigationController.viewControllers;

Zwraca tylko jeden kontroler, ale nie jest to mój główny kontroler widoku.

Jeśli spróbuję pobrać z kontrolera nawigacji:

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

Zwroty: null :

Jakieś pomysły, dlaczego? Co jeszcze mogę spróbować, aby uzyskać instancję mojego głównego kontrolera widoku?

Dzięki.

Chłopiec z ulicy
źródło
KeyWindow jest aktywnym oknem, na przykład kiedy pokazujesz UIAlertView, okno UIAlertView jest keyWindow, ale nie jest oknem AppDelegate.Jeśli chcesz pobrać rootViewController aplikacji, możesz użyć [[[UIApplication sharedApplication] delegata] okna] rootViewController ] jest lepiej.
无 夜 之 星辰

Odpowiedzi:

213

jeśli próbujesz uzyskać dostęp do rootViewControllerpliku ustawionego w pliku appDelegate. Spróbuj tego:

Cel C

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

Szybki

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

Szybki 3

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

Swift 4 i 4.2

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

Swift 5, 5.1 i 5.2

let viewController = UIApplication.shared.windows.first!.rootViewController as! YourViewController
janusfidel
źródło
3
YourViewController * rootController = (YourViewController *) [[(YourAppDelegate *) [[UIApplication sharedApplication] delegat] window] rootViewController];
Craig Moore,
1
W Swift2 musisz użyć „let appDelegate = UIApplication.sharedApplication (). Delegate as! AppDelegate”, aby wymusić rozpakowanie
Jacky
Czy istnieje sposób, aby w ten sposób przypisać dwa kontrolery, aby można było pobrać dane z obu do zegarka?
Johnny Marin
1
To jest ratunek. Dziękuję Ci! Kilka miesięcy zajęło mi znalezienie tego kawałka pysznego kodu!
ItsMeDom
37

Cel C

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

Swift 2.0

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

Szybki 5

let viewController = UIApplication.shared.keyWindow?.rootViewController
Chamath Jeevan
źródło
3
To powinna być najlepsza odpowiedź. +1 Pozostałe odpowiedzi nie będą działać, jeśli musisz odwołać się do głównego kontrolera widoku z innej struktury, od której zależy Twoja główna aplikacja.
C. Tewalt,
10

Jak sugeruje tutaj przez @ 0x7fffffff, jeśli masz UINavigationController może łatwiej będzie zrobić:

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

Kod w powyższej odpowiedzi zwraca kontroler UINavigation (jeśli go masz) i jeśli tego potrzebujesz, możesz użyć self.navigationController.

zwł
źródło
5

Jeśli nie masz dobrego powodu, w kontrolerze głównym zrób to:

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

A kiedy chcesz to powiadomić:

[[NSNotificationCenter defaultCenter] postNotificationName:@"ABCMyEvent"
                                                object:self];                
wisty
źródło
2

Szybki 3

let rootViewController = UIApplication.shared.keyWindow?.rootViewController
cybermach
źródło
1

Szybki sposób, możesz to zrobić z dowolnego miejsca, zwraca to opcjonalne, więc uważaj na to:

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

Jest to standardowa funkcja w:

https://github.com/goktugyil/EZSwiftExtensions

Esqarrouth
źródło
1

Swift 3: Chage ViewController withOut Segue i wyślij AnyObject Use: Identity MainPageViewController na docelowym ViewController

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

var mainPageNav = UINavigationController(rootViewController: mainPage)

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

lub jeśli chcesz zmienić kontrolera widoku i wysłać dane

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)  
user6857463
źródło
Jesteś najlepszym kolesiem :)
bsm-2000