简体   繁体   中英

iOS Changing rootViewController after login / logout process in Objective-C

I've read many question about this issue but I don't figure out what it doesn't work.

Basically I want to change my root controller after the user logged in the or logout from the app. I am also using the storyboard. My problem is SILoginViewController dealloc's function is never called, in this controller I send Notification and the observer is not removed, so it mess up everything, and after several "login/logout" it receives several notifications.

My AppDelegate :

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
     [self.window setFrame:[[UIScreen mainScreen] bounds]];
     BOOL isLoggedIn = [[SIUser aUser] isLoggedIn];    // from your server response

     NSString *storyboardId = isLoggedIn ? @"rootViewController" : @"navVcForLogin";
     self.window.rootViewController = [self.window.rootViewController.storyboard instantiateViewControllerWithIdentifier:storyboardId];


     return YES;
}

If the user was not logged in and he success the process a Notification is send, here is the handler where I want to change the rootViewController :

- (void)loginSuccessHandler:(id)sender
{  
      UIStoryboard *sb = [UIStoryboard storyboardWithName:@"Storyboard" bundle:nil];

      SIRootViewController * vc = [sb instantiateViewControllerWithIdentifier:@"rootViewController"];

      [UIApplication sharedApplication].keyWindow.rootViewController = vc;
}

This is the same process for the logout, and here is the notification's handler :

- (void)logoutHandler:(id)sender
{
      UIWindow *myWindow = [(SIAppDelegate *)[[UIApplication sharedApplication] delegate] window];

      SILoginViewController * vc = [sb instantiateViewControllerWithIdentifier:@"navVcForLogin"];

      [UIApplication sharedApplication].keyWindow.rootViewController = vc;
}

The easiest is to show you directly the storyboard :

故事板

The implementation in the Storyboard could seems weird but I'm using https://github.com/romaonthego/RESideMenu

I followed their storyboard implementation.

The thing is the SILoginViewController dealloc's method is never called.

But by the way it is working fine, in appearance I mean, when I run the application the behaviour is the good one, but It is sure it will mess out later on.

UPDATE

And I guess it is the common behaviour but there is no transition when the root view controller is changed and there is a black screen for a really short time when the new controller is appearing.

Black screen resolved using : in my AppDelegate.m

- (void)changeRootViewController:(UIViewController*)newRootViewController
{
    if (!self.window.rootViewController) {
        self.window.rootViewController = newRootViewController;
        return;
    }

    UIView *snapShot = [self.window snapshotViewAfterScreenUpdates:YES];
    [newRootViewController.view addSubview:snapShot];
    self.window.rootViewController = newRootViewController;
    [UIView animateWithDuration:0.3 animations:^{
        snapShot.layer.opacity = 0;
        snapShot.layer.transform = CATransform3DMakeScale(1.5, 1.5, 1.5);
    } completion:^(BOOL finished) {
        [snapShot removeFromSuperview];
    }];
}

RootViewController Switch Transition Animation

This probably kind of a duplicate question but I spent hours to figure out this problem.

[currentRootViewController willMoveToParentViewController:nil];         // notify the VC of movements

[self addChildViewController:newRootViewController];        //Add the new VC

[self transitionFromViewController: currentRootViewController toViewController: newRootViewController
                          duration: 0.15 options:UIViewAnimationOptionCurveEaseInOut
                        animations:^{
                            newRootViewController.view.frame = currentRootViewController.view.frame;
                        }
                        completion:^(BOOL finished) {       //Cleanup from the move
                            [currentRootViewController removeFromParentViewController];
                            [newRootViewController didMoveToParentViewController:self];
                        }];

The code for willMoveToParentViewController and didMoveToParentViewController will notify the ViewController of the changes, and should get your dealloc called, since there is now nothing holding onto the ViewController, unless you have a pointer to it somewhere, then you will need to nullify all your pointers to the code. The solution you tried is only half of what needs to go on to get the transition completed successfully.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM