Wie bekomme ich Root View Controller?

109

Ich benötige eine Instanz von Root View Controller.

Ich habe diese Ansätze ausprobiert:

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

Rückgabe: null :

Auch wenn ich versuche, ein Array von Controllern zu bekommen:

NSArray *viewControllers = self.navigationController.viewControllers;

Es wird nur ein Controller zurückgegeben, aber es ist nicht mein Root-View-Controller.

Wenn ich versuche, vom Navigationscontroller zu nehmen:

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

Rückgabe: null :

Irgendwelche Ideen warum? Was könnte ich sonst noch versuchen, eine Instanz meines Root View Controllers zu erhalten?

Vielen Dank.

Straßenjunge
quelle
Das keyWindow ist das aktive Fenster. Wenn Sie beispielsweise eine UIAlertView anzeigen, ist das Fenster der UIAlertView das keyWindow, aber nicht das Fenster des AppDelegate. Wenn Sie den rootViewController der Anwendung abrufen möchten, verwenden Sie möglicherweise das [[[UIApplication sharedApplication] delegate] -Fenster] rootViewController ] ist besser.
夜 之 星辰

Antworten:

213

Wenn Sie versuchen, auf die rootViewControllerin Ihrem AppDelegate festgelegten Werte zuzugreifen. Versuche dies:

Ziel c

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

Schnell

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

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

Swift 5 & 5.1 & 5.2

let viewController = UIApplication.shared.windows.first!.rootViewController as! YourViewController
janusfidel
quelle
3
YourViewController * rootController = (YourViewController *) [[(YourAppDelegate *) [[UIApplication sharedApplication] delegate] -Fenster] rootViewController];
Craig Moore
1
In Swift2 müssen Sie "let appDelegate = UIApplication.sharedApplication (). Delegate as! AppDelegate" verwenden, um das Auspacken zu erzwingen
Jacky
Gibt es eine Möglichkeit, zwei Controller auf diese Weise zuzuweisen, damit Sie Daten von beiden auf die Uhr ziehen können?
Johnny Marin
1
Dies ist ein Lebensretter. Danke dir! Ich habe Monate gebraucht, um diesen köstlichen Code zu finden!
ItsMeDom
37

Ziel c

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

Swift 2.0

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

Swift 5

let viewController = UIApplication.shared.keyWindow?.rootViewController
Chamath Jeevan
quelle
3
Dies sollte die beste Antwort sein. +1 Die anderen Antworten funktionieren nicht, wenn Sie den Root-View-Controller aus einem anderen Framework referenzieren müssen, von dem Ihre Haupt-App abhängig ist.
C. Tewalt
10

Wie hier von @ 0x7fffffff vorgeschlagen, kann es einfacher sein, UINavigationController zu verwenden:

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

Der Code in der obigen Antwort gibt den UINavigation-Controller zurück (falls vorhanden). Wenn Sie diesen benötigen, können Sie ihn verwenden self.navigationController.

insb
quelle
5

Wenn Sie keinen guten Grund haben, gehen Sie in Ihrem Root-Controller folgendermaßen vor:

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

Und wenn Sie es benachrichtigen möchten:

[[NSNotificationCenter defaultCenter] postNotificationName:@"ABCMyEvent"
                                                object:self];                
wehmütig
quelle
2

Swift 3

let rootViewController = UIApplication.shared.keyWindow?.rootViewController
Cybermach
quelle
1

Schneller Weg, Sie können dies von überall aus aufrufen. Es wird optional zurückgegeben. Achten Sie also darauf:

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

Es ist als Standardfunktion enthalten in:

https://github.com/goktugyil/EZSwiftExtensions

Esqarrouth
quelle
1

Swift 3: Chage ViewController ohne Segue und sende AnyObject Verwendung: Identity MainPageViewController auf dem Ziel-ViewController

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

var mainPageNav = UINavigationController(rootViewController: mainPage)

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

oder wenn Sie den View Controller ändern und Daten senden möchten

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
quelle
Du bist der beste Typ :)
bsm-2000