2012-11-17 6 views
37

Ich mache die Facebook Integration Tutorial, ich möchte meine MainViewViewController zeigen, wenn der Benutzer ein gültiges Token für den aktuellen Status hat, sonst möchte ich LoginViewController zeigen.AppDelegate, rootViewController und presentViewController

MainViewAppDelegate.m

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 
{ 
    if (FBSession.activeSession.state == FBSessionStateCreatedTokenLoaded) { 
     // To-do, show logged in view 
    } else { 
     // No, display the login page. 
     [self showLoginView]; 
    } 
    return YES; 
} 
- (void)showLoginView 
{ 
    UIStoryboard *mainstoryboard = [UIStoryboard storyboardWithName:@"MainStoryboard"   bundle:nil]; 
    LoginViewController* loginViewController = [mainstoryboard  instantiateViewControllerWithIdentifier:@"LoginViewController"]; 
    [self.window.rootViewController presentViewController:loginViewController animated:YES completion:NULL]; 
} 

Console Fehler:

Warning: Attempt to present <LoginViewController: 0xb492fd0> on <MainViewViewController: 0xb1bd820> whose view is not in the window hierarchy! 

Ich möchte nicht über eine Navigation verwenden.

Antwort

127

Ich hatte das gleiche Problem. Basierend auf der Antwort auf this question, fügte ich [self.window makeKeyAndVisible] kurz vor presentViewController:animated:completion: hinzu, und das reparierte es für mich.

In Ihrem Fall wird showLoginView

- (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]; 
} 
+2

Es funktioniert! Vielen Dank ! Es tut mir leid, aber ich habe nicht genug Reputation, um deine Antwort abzustimmen ... Ich hoffe, jemand anderes wird das tun;) –

+1

abgestimmt. danke für den code shebang – Viren

+1

DANKE! Endlich bekam ich die Antwort, die ich brauchte :) –

33

Manchmal modale View-Controller von window.rootViewController präsentiert & die gleiche Warnung erzeugen kann keine Wirkung. Beispiel einer solchen Hierarchie von View-Controller:

  1. [MYUITableViewController] (presented modal durch MYUIViewController)
  2. [MYUIViewController] (RootViewController von UINavigationController unten)
  3. [UINavigationController] (root)

Rufen Sie jetzt

[[UIApplication sharedApplication].keyWindow.rootViewController presentViewController:[UIViewController new] animated:YES completion:nil]; 

wird exakt diese Warnung verursachen (getestet sowohl auf iOS6 & 7 Sim)

Lösung: Statt RootViewController verwenden - verwenden, um die oberste indem sie sie präsentiert:

UIViewController *topRootViewController = [UIApplication sharedApplication].keyWindow.rootViewController; 
    while (topRootViewController.presentedViewController) 
    { 
     topRootViewController = topRootViewController.presentedViewController; 
    } 

    [topRootViewController presentViewController:yourController animated:YES completion:nil]; 
  • Manchmal wurde keyWindow durch ein Fenster mit nil rootViewController (UIAlertViews, UIActionSheets auf dem iPhone usw.) ersetzt. In diesem Fall sollten Sie die UI verwenden Fenstereigenschaften der View
+0

Das war perfekt !!! Vielen Dank ..... – Blasco73

+0

Es funktioniert perfekt. – Xiaosu

+0

Ich bekomme "Unsymmetrische Aufrufe zu Beginn/Ende aussehen Übergänge für " – Slavcho

3

Stepan Generalov's answer war die richtige für mich in Swift 3 !!!
Natürlich mit der neuen Syntax etc., so werde ich es hier kopieren:

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" mein Haupt View-Controller der Kennung in diesem Fall ist.

Ich weiß, dass es andere Möglichkeiten gibt, aber wenn Sie verschiedene URL-Schemata für die Öffnung der verschiedenen Teile Ihrer App haben müssen, müssen Sie es in AppDelegate behandeln, so ist dies, weil perfekt in der

func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {} 

Methode können Sie nur überprüfen, was url als String ist und dann entscheiden, ob Sie den oben geschriebene Code ausführen oder vielleicht ein ähnliches mit einer anderen Kennung für einen anderen view-Controller (withIdentifier)

0

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)