【问题标题】: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 ] 更好。

标签: objective-c swift ios5 uiviewcontroller uinavigationcontroller


【解决方案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)  
            

            【讨论】:

            • 你是最好的家伙:)
            猜你喜欢
            • 2012-12-02
            • 1970-01-01
            • 1970-01-01
            • 2016-03-23
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多