简体   繁体   English

iOS在Objective-C中登录/注销过程后更改rootViewController

[英]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. 我的问题是从未调用过SILoginViewController dealloc的函数,在此控制器中,我发送Notification且未删除观察者,因此它使所有内容混乱,并在多次“登录/注销”后接收到多个通知。

My AppDelegate : 我的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 : 如果用户未登录并且他成功完成了发送通知的过程,那么这里是我要更改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 故事板中的实现可能看起来很奇怪,但是我正在使用https://github.com/romaonthego/RESideMenu

I followed their storyboard implementation. 我按照他们的情节提要实施。

The thing is the SILoginViewController dealloc's method is never called. 问题是从未调用过SILoginViewController dealloc的方法。

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 黑屏使用:在我的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 RootViewController切换过渡动画

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. willMoveToParentViewControllerdidMoveToParentViewController的代码willMoveToParentViewController更改通知给ViewController,并且应该调用您的dealloc,因为现在没有任何保存在ViewController上的东西,除非您在某处有指向它的指针,否则您需要将所有指向null的指针都作空。编码。 The solution you tried is only half of what needs to go on to get the transition completed successfully. 您尝试的解决方案仅是成功完成过渡所需的一半。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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