调用transitionFromViewController切换ViewController崩溃,报错无共同父视图控制器
transitionFromViewController:崩溃的问题 这个报错我太熟悉了,核心原因就是你调用transitionFromViewController:的时候,firstVC和secondVC没有共同的父视图控制器——从错误信息里的(null)就能看出来,它们的parentViewController都是空的,完全不符合这个方法的调用前提。
先搞懂transitionFromViewController:的本质
这个方法是专门给容器视图控制器(比如自定义的TabBarController、UINavigationController这类)用的,作用是在同一个父VC的两个子VC之间做切换,同时完成视图的过渡动画。它的要求非常明确:两个子VC必须已经属于同一个父VC,或者至少在调用方法前把目标VC(secondVC)添加到父VC中。
针对你的场景,分两种情况解决:
情况1:你确实需要用容器VC管理两个子VC(比如自定义页面切换逻辑)
如果是这种场景,你不能在firstVC内部调用这个方法——因为firstVC自己是子VC,没有权限把自己替换掉,应该让父容器VC来处理切换:
- 先在父容器VC中初始化并添加
firstVC作为子VC:
// 在父容器VC的代码里 - (void)viewDidLoad { [super viewDidLoad]; FirstViewController *firstVC = [[FirstViewController alloc] init]; [self addChildViewController:firstVC]; firstVC.view.frame = self.view.bounds; [self.view addSubview:firstVC.view]; [firstVC didMoveToParentViewController:self]; // 把父VC的引用传给firstVC,用来触发切换 firstVC.containerVC = self; }
- 在
firstVC的按钮点击事件里,通知父容器VC执行切换:
// FirstViewController.m - (IBAction)switchButtonTapped:(id)sender { SecondViewController *secondVC = [[SecondViewController alloc] init]; [self.containerVC switchToViewController:secondVC fromVC:self]; }
- 父容器VC中实现切换逻辑:
// 父容器VC的方法 - (void)switchToViewController:(UIViewController *)toVC fromVC:(UIViewController *)fromVC { [self addChildViewController:toVC]; toVC.view.frame = self.view.bounds; [self transitionFromViewController:fromVC toViewController:toVC duration:0.3 options:UIViewAnimationOptionTransitionNone animations:nil completion:^(BOOL finished) { // 切换完成后,移除旧的子VC,完成生命周期 [fromVC removeFromParentViewController]; [toVC didMoveToParentViewController:self]; }]; }
情况2:你只是想做普通的页面跳转(不需要容器VC)
如果你的需求只是从firstVC跳转到secondVC,那完全没必要用transitionFromViewController:——这个方法不是用来做普通页面跳转的。直接用下面两种方式更简单:
- 如果你的页面在导航控制器(
UINavigationController)栈中:
- (IBAction)switchButtonTapped:(id)sender { SecondViewController *secondVC = [[SecondViewController alloc] init]; [self.navigationController pushViewController:secondVC animated:YES]; }
- 如果是模态弹出页面:
- (IBAction)switchButtonTapped:(id)sender { SecondViewController *secondVC = [[SecondViewController alloc] init]; [self presentViewController:secondVC animated:YES completion:nil]; }
最后再总结下你的错误根源
你直接在firstVC中调用[self transitionFromViewController:firstVC toViewController:secondVC ...],这里的self是firstVC,而此时firstVC本身可能没有父VC,secondVC也没有被添加到任何父VC中,两者的parentViewController都是nil,完全不符合transitionFromViewController:的调用前提,所以才会抛出那个异常。
内容的提问来源于stack exchange,提问作者user2688045

