DidFinishLaunchingWithOptions get called before storyboards are loaded?

I have an application that implements Facebook login at startup using code very similar to this: Facebook Scrumptious Tutorial , with the exception of Storyboard.

The main point of the code is that when the application starts, the application delegate checks if you are already logged in, and if you use it directly to the main view, and if not, it asks for the main view, enter the login so that the user can log in the system.

I already solved my other problem, having the opportunity to tell the main view in the storyboard, to present another view, getting the main view from the hierarchy of views, and then calling segue in the view. Everything works fine, however I have one last problem:

As far as I know, it is assumed that the didFinishLaunchingWithOptions application will be called after the storyboard is fully loaded. However, in my code, if I try to tell the main view about the view of another view, it gives me an error basically saying that it is not loaded yet (Warning: attempt to present <QLoginViewController: 0x955c020> on <UINavigationController: 0xa28c6e0> whose look is not in hierarchy of windows!).

If I tell him to submit a presentation after a delay, however:

[self performSelector:@selector(showLoginViewAnimated:) withObject:NO afterDelay:.001];

( showLoginViewAnimated: , ), .

- , , ? , , , , ...

appDelegate didFinishLaunchingWithOptions:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    // Override point for customization after application launch.

    self.navigationController = (UINavigationController *)self.window.rootViewController;

    // Navigation Bar Color
    [[UINavigationBar appearance] setTintColor:[UIColor colorWithRed:255.0/255.0 green:128.0/255.0 blue:60.0/255.0 alpha:1.0]];


    /* Facebook Login */    // THIS IS THE RELEVANT CODE: 
    // See if we have a valid token for the current state
    if (FBSession.activeSession.state == FBSessionStateCreatedTokenLoaded) {
        // Yes, valid token exists - open the session (don't display login page)
        [self openSession];
    } else {
        // No, valid token does not exist -  display the login page.
        if ([self.navigationController isViewLoaded]) {
            [self showLoginViewAnimated:NO];   // MY ATTEMPT TO AVOID USING THE DELAY IF POSSIBLE
        }
        else {
            [self performSelector:@selector(showLoginViewAnimated:) withObject:NO afterDelay:.001]; // Delay needed to allow for storyboard loading
        }
    }

    return YES;
}

showLoginViewAnimated: code:

- (void)showLoginViewAnimated:(BOOL)animated
{
    UIViewController *topViewController = [self.navigationController topViewController];
    UIViewController *presentedViewController = [topViewController presentedViewController];

    // If the login screen is not already displayed, display it. If the login screen is
    // displayed, then getting back here means the login in progress did not successfully
    // complete. In that case, notify the login view so it can update its UI appropriately.

    if (![presentedViewController isKindOfClass:[QLoginViewController class]]) {
        if (animated) {
            [topViewController performSegueWithIdentifier:@"ShowLoginViewAnimated" sender:self];
        }
        else {
            [topViewController performSegueWithIdentifier:@"ShowLoginViewStatic" sender:self];
        }
    }
    else {
        QLoginViewController *loginViewController = (QLoginViewController *)presentedViewController;
        [loginViewController loginFailed];
    }
}

, , showLoginViewAnimated: didFinishLaunchingWithOptions, :

self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.viewController = [[MainViewController alloc] initWithNibName:@"MainViewController" bundle:nil];
self.navController = [[UINavigationController alloc] initWithRootViewController:self.viewController];

self.window.rootViewController = self.navController;
[self.window makeKeyAndVisible];

, 100% , , , . , , didFinishLaunchingWithOptions , , , , , , ? ...

? !

: , - , . (BOOL) showLoginView , - ( ).

(-) appDelegate didFinishLaunchingWithOptions:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    // Override point for customization after application launch.
    self.viewController = [[FBLViewController alloc] initWithNibName:@"FBLViewController" bundle:nil];
    self.navController = [[UINavigationController alloc] initWithRootViewController:self.viewController];

    self.window.rootViewController = self.navController;
    [self.window makeKeyAndVisible];


    // See if we have a valid Facebook token for the current state
    if (FBSession.activeSession.state == FBSessionStateCreatedTokenLoaded) {
        // Yes, so just open the session (this won't display any UX).
        [self openSession];
    }
    else {
        // No, display the login page.
        [self showLoginView];
    }

    return YES;
}

showLoginView (non-storyboard):

- (void)showLoginView
{
    UIViewController *topViewController = [self.navController topViewController];
    UIViewController *presentedViewController = [topViewController presentedViewController];

    // IF the login screen is not already displayed, display it. If the login screen is
    // displayed, then getting back here means the login in progress did not successfully
    // complete. In that case, notify the login view so it can update its UI appropriately.

    if (![presentedViewController isKindOfClass:[FBLLoginViewController class]]) {
        FBLLoginViewController *loginViewController = [[FBLLoginViewController alloc] initWithNibName:@"FBLLoginViewController" bundle:nil];
        loginViewController.delegate = self;
        [topViewController presentViewController:loginViewController animated:NO completion:nil];
    }
    else {
        FBLLoginViewController *loginViewController = (FBLLoginViewController *)presentedViewController;
        [loginViewController loginFailed];
    }
}
+5
2

didFinishLaunchingWithOptions:

[self.window makeKeyAndVisible];

Facebook.

+9

, , : , , , . - viewDidLoad viewWillAppear , , .

+1

All Articles