2012-11-17 19 views
37

Sto facendo il tutorial di integrazione di Facebook, voglio mostrare il mio MainViewViewController se l'utente ha un token valido per lo stato corrente altrimenti voglio mostrare LoginViewController.AppDelegate, rootViewController e 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]; 
} 

errore Console:

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

Non voglio usare un navigationController.

risposta

127

Ho avuto lo stesso problema. In base alla risposta allo this question, ho aggiunto [self.window makeKeyAndVisible] poco prima dello presentViewController:animated:completion: e l'ho risolto per me.

Nel tuo caso, showLoginView diventa

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

Funziona! Grazie ! Mi dispiace ma non ho abbastanza reputazioni per votare la tua risposta ... Spero che qualcun altro lo faccia;) –

+1

votato. grazie per il codice shebang – Viren

+1

GRAZIE! Finalmente ho ottenuto la risposta che mi serviva :) –

33

che talvolta si manifesta controller di vista modale dalla window.rootViewController può produrre lo stesso avvertimento & non hanno alcun effetto. esempio di tale gerarchia di controller di vista:

  1. [MYUITableViewController] (presentata modally da MYUIViewController)
  2. [MYUIViewController] (RootViewController di UINavigationController sotto)
  3. [UINavigationController] (root

Ora chiamando

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

causerà questo avvertimento esatto (testato sia su iOS6 & 7 Sim)

Soluzione: Invece di utilizzare RootViewController - utilizzare quello superiore presentata da esso:

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

    [topRootViewController presentViewController:yourController animated:YES completion:nil]; 
  • A volte keyWindow potrebbe essere stato sostituito da window con nil rootViewController (che mostra UIAlertViews, UIActionSheets su iPhone, ecc.), In tal caso dovresti usare l'interfaccia utente Proprietà della finestra di visualizzazione.
+0

Questo era perfetto !!! Grazie mille ..... – Blasco73

+0

Funziona perfettamente. – Xiaosu

+0

Ricevo "Chiamate sbilanciate per iniziare/terminare transizioni di aspetto per " – Slavcho

3

Stepan Generalov's answer era quella giusta per me in Swift 3 !!!
Naturalmente con la nuova sintassi ecc quindi mi limiterò copiarlo qui:

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" è identificatore mio principale del controller della vista in questo caso.

So che ci sono altri modi, ma se avete bisogno di avere diversi schemi URL per l'apertura di diverse parti della vostra applicazione, è necessario gestire in AppDelegate quindi questo è perfetto, perché nel metodo

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

, è possibile basta controllare che cosa url è come String e poi decidere se si esegue il codice scritto sopra o forse uno simile con un identificatore diverso per un altro controller della vista (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) 
Problemi correlati