如何从推控制器获取RootViewController?

所以,我从RootViewController推入一个视图控制器,如:

 [self.navigationController pushViewController:anotherViewController animated:YES];

但是,从anotherViewController现在,我想再次访问RootViewController。

我尝试着

 //(在另一个ViewController里面)
 /// RootViewController * root =(RootViewController *)self.parentViewController;  //不
 // 呃
 RootViewController * root =(RootViewController *)[self.navigationController.viewControllers objectAtIndex:0];  //是的 有用

我不知道为什么这个工作,我不知道如果它是最好的办法做到这一点。 有人可以评论一个更好的方式来从你已经推入到RootViewController的导航控制器的控制器中获取RootViewController,以及我做的方式是否可靠?

使用UINavigationController的viewControllers属性。 示例代码:

 // Inside another ViewController NSArray *viewControllers = self.navigationController.viewControllers; UIViewController *rootViewController = [viewControllers objectAtIndex:viewControllers.count - 2]; 

这是获得“后退”视图控制器的标准方式。 objectAtIndex:0的原因是因为你试图访问的视图控制器也是根视图控制器,如果你在导航中更深入,后视图将不会和根视图一样。

Swift版本:

 var rootViewController = self.navigationController?.viewControllers.first 

ObjectiveC版本:

 UIViewController *rootViewController = [self.navigationController.viewControllers firstObject]; 

其中self是UINavigationController中embedded的UIViewController的一个实例。

几乎所有这些答案中提到的同一事物的略微不那么丑陋的版本:

 UIViewController *rootViewController = [[self.navigationController viewControllers] firstObject]; 

在你的情况下,我可能会做这样的事情:

在你的UINavigationController子类中

 - (UIViewController *)rootViewController { return [[self viewControllers] firstObject]; } 

那么你可以使用:

 UIViewController *rootViewController = [self.navigationController rootViewController]; 

编辑

OP在评论中询问了一处房产。

如果你喜欢,你可以通过像self.navigationController.rootViewController这样的东西来访问它,只需要在你的头文件中添加一个readonly属性即可:

 @property (nonatomic, readonly, weak) UIViewController *rootViewController; 

对于所有对快速扩展感兴趣的人,这就是我现在使用的:

 extension UINavigationController { var rootViewController : UIViewController? { return self.viewControllers.first as? UIViewController } } 

作为@ dulgan答案的补充,使用firstObject over objectAtIndex:0总是一个好办法,因为如果数组中没有对象,则第一个返回nil,后一个则抛出exception。

 UIViewController *rootViewController = self.navigationController.viewControllers.firstObject; 

或者,创build一个名为UINavigationController+Additions的类别,并在其中定义您的方法将是一个很大的优势。

 @interface UINavigationController (Additions) - (UIViewController *)rootViewController; @end @implementation UINavigationController (Additions) - (UIViewController *)rootViewController { return self.viewControllers.firstObject; } @end 

如何问UIApplication的 单身人士的keyWindow ,并从该UIWindow要求的根视图控制器(它的rootViewController属性):

 UIViewController root = [[[UIApplication sharedApplication] keyWindow] rootViewController]; 

在这里,我想出了从任何地方导航到根的通用方法。

  1. 您可以使用这个类创build一个新的Class文件,以便在项目的任何地方都可以访问它:

     import UIKit class SharedControllers { static func navigateToRoot(viewController: UIViewController) { var nc = viewController.navigationController // If this is a normal view with NavigationController, then we just pop to root. if nc != nil { nc?.popToRootViewControllerAnimated(true) return } // Most likely we are in Modal view, so we will need to search for a view with NavigationController. let vc = viewController.presentingViewController if nc == nil { nc = viewController.presentingViewController?.navigationController } if nc == nil { nc = viewController.parentViewController?.navigationController } if vc is UINavigationController && nc == nil { nc = vc as? UINavigationController } if nc != nil { viewController.dismissViewControllerAnimated(false, completion: { nc?.popToRootViewControllerAnimated(true) }) } } } 
  2. 您的项目中的任何地方使用:

     { ... SharedControllers.navigateToRoot(self) ... }