如何获得根视图控制器?

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

我试过这些方法:

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

返回: 无效:

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

NSArray *viewControllers = self.navigationController.viewControllers;

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

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

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

返回: 无效:

知道为什么吗? 我还可以尝试获取根视图控制器的哪些实例?

谢谢。

165061 次浏览

如果你想访问你在应用程序代理中设置的 rootViewController,试试下面的方法:

目标 C

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

斯威夫特

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

正如@0x7ffffff 所建议的 给你,如果你有 UINavigationController,那么做起来会更容易:

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

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

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

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

当你想通知的时候:

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

快速的方法,你可以在任何地方调用它,它返回可选的,所以要小心:

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

目标 C

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

Swift 2.0

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

Swift 5

let viewController = UIApplication.shared.keyWindow?.rootViewController

Swift 3: 改变 ViewController 而不用 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)

Swift 3

let rootViewController = UIApplication.shared.keyWindow?.rootViewController

对于 斯威夫特5号及以后,我建议使用以下方法:

UIApplication.shared.windows.last?.rootViewController

使用 。最后将返回顶视图控制器处于活动状态。

. first 有时不适用于需要 顶部及启动窗口的库。

例如: 暴徒。我有广告没有显示,发现我正在调用下面的隐藏窗口时使用表格或全屏幕封面。

注意 : View 希望在 NavigationView 中显示所需的广告,否则将不会运行广告。

示例: NavigationView { View1()}

我希望它有用。

IOS15

随着场景和一些 API 被弃用(比如 UIApplication.shared.keyWindow) ,我发现最普遍的方法是这样的:

let scene = UIApplication.shared.connectedScenes
.first(where: { $0.activationState == .foregroundActive }) as? UIWindowScene


let rootViewController = scene?
.windows.first(where: { $0.isKeyWindow })?
.rootViewController

注意: 如果你的应用程序真的支持多个窗口/场景,这意味着你有多个“根视图控制器”,这个代码不适合你:)