I\'m doing the Facebook integration tutorial, I want to show my MainViewViewController if the user has a valid token for the current state otherwise I want to show LoginView
Sometimes presenting modal view controller from window.rootViewController may produce the same warning & have no effect. Example of such hierarchy of view controllers:
Now calling
[[UIApplication sharedApplication].keyWindow.rootViewController presentViewController:[UIViewController new] animated:YES completion:nil];
will cause this exact warning (tested both on iOS6 & 7 Sim)
Solution: Instead of using rootViewController - use the top one presented by it:
UIViewController *topRootViewController = [UIApplication sharedApplication].keyWindow.rootViewController;
while (topRootViewController.presentedViewController)
{
topRootViewController = topRootViewController.presentedViewController;
}
[topRootViewController presentViewController:yourController animated:YES completion:nil];
I had the same issue. Based on the answer to this question, I added [self.window makeKeyAndVisible]
just before presentViewController:animated:completion:
, and that fixed it for me.
In your case, showLoginView becomes
- (void)showLoginView
{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
LoginViewController *loginViewController = [storyboard instantiateViewControllerWithIdentifier:@"LoginViewController"];
[self.window makeKeyAndVisible];
[self.window.rootViewController presentViewController:loginViewController animated:YES completion:NULL];
}
You can launch a new viewController from root like this in Objective-C
UIViewController *presenter = ((AppDelegate *)[[UIApplication sharedApplication] delegate]).window.rootViewController;
[presenter presentViewController:yourViewController animated:YES completion:nil];
Don't forget to add this:
#import "AppDelegate.h"
Stepan Generalov's answer was the right one for me in Swift 3!!!
Of course with the new syntax etc. so I'll copy it in here:
let sb = UIStoryboard(name: "Main", bundle: nil)
let vc = sb.instantiateViewController(withIdentifier: "MainApp") as! ViewController
var topRootViewController: UIViewController = (UIApplication.shared.keyWindow?.rootViewController)!
while((topRootViewController.presentedViewController) != nil){
topRootViewController = topRootViewController.presentedViewController!
}
topRootViewController.present(vc, animated: true, completion: nil)
"MainApp" is my main view controller's identifier in this case.
I know there are other ways but if you need to have different URL schemes for opening different parts of your App, you must handle it in AppDelegate so this is perfect because in the
func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {}
method, you can just check what url
is as a String and then decide if you execute the above written code or maybe a similar one with a different identifier for an other view controller (withIdentifier
)
In Swift 3 :-
let storyboard = UIStoryboard(name: "Login", bundle: nil)
let viewController = storyboard.instantiateViewController(withIdentifier: "LoginViewController")
window?.makeKeyAndVisible()
window?.rootViewController?.present(viewController, animated: true, completion: nil)
In case, when you're not using a storyboard. First you need to create YourViewController. Go File -> New -> File... (or shortCut - command + N)
After that, choose Cocoa Touch Class. Click Next, or Enter
Than type name for your viewController and click Next
#import "AppDelegate.h"
#import "YourViewController.h"
@interface AppDelegate ()
@end
@implementaion AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Init window
self.window = [[UIWindow alloc] initWithFrame:UIScreen.mainScreen.bounds];
[self.window makeKeyAndVisible];
// Init YourViewController
YourViewController *viewController = [[YourViewController alloc] init];
// Init YourNavigationController
UINavigationController *navigationContoller = [[UINavigationController alloc] initWithRootViewController: viewController];
// Set rootViewController
self.window.rootViewController = navigationContoller;
return YES;
}
@end
Swift 3/4 Example
import UIKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
//1-st step
window = UIWindow(frame: UIScreen.main.bounds)
window?.makeKeyAndVisible()
//2-nd - create a window root controller, and create a layout
let layout = UICollectionViewFlowLayout()
window?.rootViewController = UINavigationController(rootViewController: HomeController(collectionViewLayout: layout))
return true
}