Search code examples
iosobjective-cparsinguitabbarcontrolleruiwindow

Reassign UIWindow rootViewController from UIViewController to UITabBarController containing UINavigationControllers


I am currently having an issue with my login flow. The logic is all there but the animation from the login view to the main view is weird.

Heres a side note: The main view is a UITabBarController with 5 UINavigationControllers and the login view is just a UIViewController

So first I determine in - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions , whether the current user is already logged in (I am using Parse to handle that), if their not then set the UIWindows rootViewController to be the Login controller. Else, set the UIWindows rootViewController to be the main view.

This works fine... Assume that the user is logged in on app launch. Okay cool, it shows the main View. I then sign out and everything is working as expected. I switch the UIWindows rootViewController by running this method:

- (void)showLogin {
    self.activity = nil;
    self.chat = nil;
    self.create = nil;
    self.notification = nil;
    self.more = nil;

    self.loginViewController = nil; 
    if (!self.loginViewController) { // this check is redundant i feel lol
        self.loginViewController = [[PHLoginRegisterViewController alloc] init];
    }

    [UIView transitionWithView:self.window
                      duration:0.5
                       options:UIViewAnimationOptionTransitionCrossDissolve
                    animations:^{
                        self.window.rootViewController = self.loginViewController;
                    } completion:^(BOOL finished) {
                        self.activity = [[PHActivityViewController alloc] init];
                        self.chat = [[PHGlobalChatViewController alloc] init];
                        self.notification = [[PHNotificationsViewController alloc] init];
                        self.more = [[PHMoreViewController alloc] init];
                        [self.tabBarController setViewControllers:@[[[UINavigationController alloc] initWithRootViewController:self.activity],
                                                                    [[UINavigationController alloc] initWithRootViewController:self.chat],
                                                                    [[UINavigationController alloc] init],
                                                                    [[UINavigationController alloc] initWithRootViewController:self.notification],
                                                                    [[UINavigationController alloc] initWithRootViewController:self.more]]];
                        [self.tabBarController setSelectedIndex:0];
                    }];
}

Okay, so the login view is now shown with a nice transition... Then when I attempt to login, everything works fine, but when the transition is happening login->main, the entire main view (except for the position of the UITabBar of the UITabBarController) is basically set -20px for a brief moment, then gets reset to its expected position... Heres two screenshots of when the login is transitioning to the main view, then when it is done transitioning... During Transition After Transition

I've tested this exact implementation without a UITabBarController and it doesn't do this. This sorta GLITCH issue. Any ideas that anyone can pass along?

I want to know if its possible to do this login->main and main->login transition without having to implement the main's viewDidAppear or viewWillAppear methods.

For example, in the main views viewDidAppear,

if (user is logged in)

        [self presentViewController:login animated:NO]

This causes the main screen to be seen for a brief moment before the loginview is shown, which I don't want.


Solution

  • I think the problem is that before your transition is completed, the auto layout process is not triggered, so your view is the position it is in your xib design.

    I have an idea to work around this, whenever the app is launching, you use you main view controller as the root view controller, and if you need login, in main view controller's viewDidLoad, you load the login view controller and add it's view as the top subview of main view controller, this will solve problem that presentation has.

    The only drawback is that your login view need a opaque background.