如何获取根视图控制器?

Posted

技术标签:

【中文标题】如何获取根视图控制器?【英文标题】:How to get root view controller? 【发布时间】:2012-09-07 05:51:51 【问题描述】:

我需要一个根视图控制器的实例。

我尝试了这些方法:

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

返回:null

当我尝试获取控制器数组时:

NSArray *viewControllers = self.navigationController.viewControllers;

它只返回一个控制器,但它不是我的根视图控制器。

如果我尝试从导航控制器中获取:

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

返回:null

任何想法为什么?我还能尝试获取根视图控制器的实例吗?

谢谢。

【问题讨论】:

keyWindow是活动窗口,例如,当你显示一个UIAlertView时,UIAlertView的窗口是keyWindow但不是AppDelegate的窗口。如果你想获取应用程序的rootViewController,可以使用[[[ UIApplication sharedApplication] delegate] window] rootViewController ] 更好。 【参考方案1】:

如果您尝试访问您在 appDelegate 中设置的rootViewController。试试这个:

Objective-C

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

斯威夫特

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

斯威夫特 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

【讨论】:

YourViewController *rootController =(YourViewController *)[[(YourAppDelegate *) [[UIApplication sharedApplication]delegate] window] rootViewController]; 在 Swift2 中,你必须使用 "let appDelegate = UIApplication.sharedApplication().delegate as!AppDelegate" 来强制解包 有没有办法以这种方式分配两个控制器,以便您可以从两个控制器中提取数据到手表? 这是救命稻草。谢谢!我花了几个月的时间才找到这段美味的代码! AVPictureInPictureController 或 AVPlayerViewController 会创建新窗口,类为 PGHostedWindow 并将其添加到 windows 数组中,因此,使用第一个窗口可能会导致崩溃【参考方案2】:

Objective-C

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

Swift 2.0

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

斯威夫特 5

let viewController = UIApplication.shared.keyWindow?.rootViewController

【讨论】:

这应该是最佳答案。 +1 如果您需要从您的主应用程序所依赖的不同框架中引用根视图控制器,则其他答案将不起作用。 值得指出的是,keyWindow 在 ios13 中已被弃用【参考方案3】:

正如@0x7fffffff 所建议的here,如果你有 UINavigationController 会更容易做到:

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

上面答案中的代码返回 UINavigation 控制器(如果你有的话),如果这是你需要的,你可以使用self.navigationController

【讨论】:

【参考方案4】:

对于 Swift 5 及更高版本,我建议使用此方法:

UIApplication.shared.windows.last?.rootViewController

使用 .last 将返回顶部视图控制器处于活动状态。

.first 有时不适用于需要 top & actived 上的窗口的库。

例如:Admob。我的广告没有显示,发现我在使用 sheet 或 fullscreenCover 时调用了下面的隐藏窗口。

注意:View要在NavigationView中展示广告,如果没有,广告将不会投放。

示例:NavigationView View1()

希望有用。

【讨论】:

【参考方案5】:

除非你有充分的理由,否则在你的根控制器中这样做:

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

当你想通知它时:

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

【讨论】:

【参考方案6】:

斯威夫特 3

let rootViewController = UIApplication.shared.keyWindow?.rootViewController

【讨论】:

【参考方案7】:

Swift 的方式,你可以从任何地方调用它,它返回可选的,所以要注意:

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

它作为标准功能包含在:

https://github.com/goktugyil/EZSwiftExtensions

【讨论】:

【参考方案8】:

Swift 3:Chage ViewController withOut Segue 并发送 AnyObject 使用:目标 ViewController 上的标识 MainPageViewController

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

var mainPageNav = UINavigationController(rootViewController: mainPage)

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

或者如果您想更改视图控制器并发送数据

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)  

【讨论】:

你是最好的家伙:)

以上是关于如何获取根视图控制器?的主要内容,如果未能解决你的问题,请参考以下文章

如何将字符串从根视图控制器传递到另一个视图?

引导 React 渲染器:如何在应用启动时获取对根视图的引用?

在 iOS 13 中获取根视图控制器的正确方法是啥?

如何在 symfony 2 中获取根路由

适合用于后台获取?

如何获取已被约束拉伸的视图的高度? - iOS