2012-11-17 12 views
37

Robię samouczek integracji Facebook, chcę pokazać mój MainViewViewController, jeśli użytkownik ma ważny token dla bieżącego stanu w przeciwnym razie chcę pokazać LoginViewController.AppDelegate, rootViewController i 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]; 
} 

błąd konsoli:

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

Nie chcę używać NavigationController.

Odpowiedz

127

Miałem ten sam problem. Na podstawie odpowiedzi na this question dodałem [self.window makeKeyAndVisible] tuż przed presentViewController:animated:completion: i to naprawiłem dla mnie.

W twoim przypadku, showLoginView staje

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

To działa! dzięki ! Przykro mi, ale nie mam wystarczająco dużo reputacji, aby zagłosować na twoją odpowiedź ... Mam nadzieję, że ktoś to zrobi;) –

+1

głosowało w górę. dzięki za kod shebang – Viren

+1

DZIĘKUJEMY! W końcu dostałem odpowiedź, której potrzebowałem :) –

33

Czasami prezentuje modalne kontroler widok z window.rootViewController mogą produkować ten sam ostrzeżenia & nie mają żadnego wpływu. Przykład takiej hierarchii widzenia regulatorów:

  1. [MYUITableViewController] (przedstawiony modalne przez MYUIViewController)
  2. [MYUIViewController] (rootViewController z UINavigationController poniżej)
  3. [UINavigationController] (Root)

Teraz dzwonisz pod numer

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

spowoduje dokładnie to ostrzeżenie (testowane zarówno na iOS6 & 7 SIM)

Rozwiązanie: Zamiast rootViewController - użyj Top One przedstawiony przez niego:

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

    [topRootViewController presentViewController:yourController animated:YES completion:nil]; 
  • Czasami keyWindow mogło zostać zastąpione przez okno z zerowym rootViewController (pokazujące UIAlertViews, UIActionSheets na iPhone, itp.), W takim przypadku powinieneś użyć UI Właściwość okna widoku.
+0

To było idealne !!! Dziękuję bardzo ..... – Blasco73

+0

Działa doskonale. – Xiaosu

+0

Otrzymuję komunikat "Niezrównoważone wywołania przejść do początku/końca zmiany wyglądu dla " – Slavcho

3

Stepan Generalov's answer była słuszna dla mnie w Swift 3 !!!
oczywiście z nowej składni itp więc będę skopiować go tutaj:

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” to identyfikator mojego głównego sterownika widzenia w tej sprawie.

Wiem, że są inne sposoby, ale jeśli chcesz mieć różne schematy URL do otwierania różnych części aplikacji, należy poradzić się AppDelegate więc jest to idealne miejsce, ponieważ w metodzie

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

, można po prostu sprawdzić co url jest jako String, a następnie zdecydować, czy wykonać powyższą napisany kod, a może podobną jedną z innym identyfikatorem dla innego kontrolera widoku (withIdentifier)

0

w 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)