我有一个标签栏控制器,每个标签都有一个导航控制器。导航控制器具有视图控制器。然后,如果用户需要登录或注销,我的登录控制器没有连接到我用以下代码调用的标签栏控制器。
当我尝试根据用户是否登录时有条件地推送视图控制器时,我看到一些奇怪的行为。
我的逻辑看起来像这样:
if(currentUser){
}else{
LoginViewController *svc = [self.storyboard instantiateViewControllerWithIdentifier:@"Login"];
svc.hidesBottomBarWhenPushed = YES;
[self.navigationController pushViewController:svc animated:YES];
}
当推送视图时,看起来好像已经按下了登录视图,并且在其上推送了另一个登录视图。
对于注销,我在segue中有相同的代码:
if ([segue.identifier isEqualToString:@"LogoutView"]) {
[self logOut];
LoginViewController *svc = [self.storyboard instantiateViewControllerWithIdentifier:@"Login"];
svc.hidesBottomBarWhenPushed = YES;
[self.navigationController pushViewController:svc animated:YES];
}
在这个例子中,我看到相同的双推,每次我点击我的登录按钮时,它会推送另一个登录视图。这种情况无限发生。然后我收到警告:
在意外状态下完成导航转换。 导航栏子视图树可能已损坏。
当我在导航中按回来时,应用程序崩溃并显示错误:
NSInvalidArgumentException',原因:'无法将自己添加为子视图'
我没有正确推送登录视图控制器吗?
答案 0 :(得分:2)
Segues实例化新控制器,并执行从源控制器到目标控制器的转换。因此,您既不应该在代码中实例化控制器,也不应该使用pushViewController推送它:animated:。如果按钮(而不是控制器)正在触发segue,那么您只需要获取对目标控制器的引用(segue.destinationViewController),并使用它来隐藏底栏,
-(void)prepareForSegue:(UIStoryboardSegue *) segue sender:(id) sender {
if ([segue.identifier isEqualToString:@"LogoutView"]) {
[self logOut];
LoginViewController *svc = segue.destinationViewController;
svc.hidesBottomBarWhenPushed = YES;
}
}
如果您需要有条件地执行此操作,则应直接从控制器连接segue,而不是按钮。然后你需要调用performSegueWithIdentifier:在某种方法中你有逻辑来确定应该执行哪个(或者是否)segue。