I have a view that is UIViewController
(root) that handles ads and a UINavigationController
. In that UINavigationController I have typical layers of controllers. In my custom settings table view controller, I have a button to contact me for support. When the user clicks this button I create a MFMailComposeViewController
and would like to present it. I can't present it from the settings table view as it will be underneath my ads, so I need to reference the root view and present it from there. I've tried self.parentViewController.parentViewController
where self is the settings table view, but that doesn't work. How should I reference this. It seems like a bad design to have to reference the root view directly and pass it to the settings view.
-
Have you tried self.navigationController? I'm unclear on how your view hierarchy is set up.– jaminguyMay 11, 2011 at 18:19
5 Answers
Get the current keyWindow:
UIWindow *window = [UIApplication sharedApplication].keyWindow;
Get its rootViewController:
UIViewController *rootViewController = window.rootViewController;
NOTE: If an UIAlertView
is currently being shown, a new window is being created and assigned to be the keyWindow. There might be other exceptional cases as well that will not keep your application window to be the keyWindow.
-
1This only works on 4.0+ by the way. UIWindow did not have a rootViewController property prior to 4.0. May 11, 2011 at 23:02
-
1@Jesse good point - I am so glad I do not have to support those ancient bricks anymore ;).– TillMay 12, 2011 at 8:33
-
-
10Just a quick warning. This will not work if its called with a ui alert on screen. May 7, 2013 at 8:05
-
3@ChrisMitchelmore a UIAlert opens a new window, and makes it the key-window as long as it is displayed.– TillMay 7, 2013 at 12:35
In my experience, this is the ideal solution to get the rootViewController
:
[[[[UIApplication sharedApplication] delegate] window] rootViewController]
Note: In-case of an active UIAlert
or UIActionSheet
, you get the Alert or Action Sheet as your key window.
-
+1 This is the only safe, reliable way to do it. Took ages for me to track down an alert + keyWindow bug, and this post saved me! Apr 1, 2014 at 0:23
-
3Second that! The keyWindow approach (currently marked as the correct answer) is not reliable, since the key window can change. Aug 14, 2014 at 9:01
-
also had a bug with using the keyWindow during a UIAlertView ... thank you for this! this is the best method to use.– manroeJun 3, 2016 at 18:12
Use the app singleton. Something like:
[[[UIApplication sharedApplication] delegate] rootViewController]
should get it if your viewController that is the root is named rootViewController
You can always solve this with 1 line of code but I recommend this Swift way to do it, you can call this from anywhere, its also crash and bug safe:
/// 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
}
Its included as a standard function in:
Get the UIApplication object. Cycle through the windows array to find the keyWindow. And then get the rootViewController property.