关闭堆栈中较低的ViewController不会按预期运行

我正在构建一个复杂的应用程序,中间有一个分支。

在应用程序的某个时刻,会出现一个特定的UIViewController,我们将其称为mainViewController (缩短的mainVC )。

mainVC通过代码使用以下代码呈现另一个视图控制器(出于隐私原因,我删除了部分代码):

 UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"SecondaryStoryboard" bundle:secondaryBundle]; SecondViewController *secondVC = [storyboard instantiateInitialViewController]; [self presentViewController:secondVC animated:YES completion:nil]; 

因此, secondVC将在稍后呈现另一个名为thirdVC视图控制器。 这是使用自定义segue完成的,在上面的代码中使用的故事板中设置,代码如下所示:

 @implementation VCCustomPushSegue - (void)perform { UIView *sourceView = ((UIViewController *)self.sourceViewController).view; UIView *destinationView = ((UIViewController *)self.destinationViewController).view; UIWindow *window = [[[UIApplication sharedApplication] delegate] window]; destinationView.center = CGPointMake(sourceView.center.x + sourceView.frame.size.width, destinationView.center.y); [window insertSubview:destinationView aboveSubview:sourceView]; [UIView animateWithDuration:0.4 animations:^{ destinationView.center = CGPointMake(sourceView.center.x, destinationView.center.y); sourceView.center = CGPointMake(0 - sourceView.center.x, destinationView.center.y); } completion:^(BOOL finished){ [self.sourceViewController presentViewController:self.destinationViewController animated:NO completion:nil]; }]; } @end 

正如您所看到的,这个segue使用自定义动画(从右到左的幻灯片)以模态方式(通过使用presentViewController:显示目标视图控制器。

所以基本上到这里一切都很好。 我用经典的模态动画(从底部向上滑动)呈现第二个thirdVC ,并使用我的自定义过渡呈现第三个thirdVC

但是当我想要解雇第三个thirdVC ,我想要的是直接回到mainVC 。 所以我从第三个thirdVC调用以下thirdVC

 self.modalTransitionStyle = UIModalTransitionStyleCoverVertical; [self.presentingViewController.presentingViewController dismissViewControllerAnimated:_animate completion:nil]; 

这样,我正在调用dismissViewControllerAnimated:直接在mainVCmainVC (由self.presentingViewController.presentingViewController引用),我期待第三个thirdVC被动画解散,而第二个secondVC只是在没有动画的情况下消失。

正如Apple在UIViewController类文档中所说:

呈现视图控制器负责解除它所呈现的视图控制器 。 如果在呈现的视图控制器本身上调用此方法,它会自动将消息转发给呈现视图控制器。

如果您连续呈现多个视图控制器 ,从而构建一堆呈现的视图控制器,则在堆栈中较低的视图控制器上调用此方法会解除其直接子视图控制器和堆栈上该子级上方的所有视图控制器 。 发生这种情况时, 只有最顶层的视图以动画方式被删除 ; 任何中间视图控制器都可以从堆栈中删除。 最顶层的视图使用其模态过渡样式被忽略,这可能与堆栈中较低的其他视图控制器使用的样式不同。

问题是它不会发生什么。 在我的场景中,第三个thirdVC消失,并显示第二个secondVC被解雇,经典模态幻灯片到底部动画。

我究竟做错了什么 ?


编辑:

所以@codeFi的答案可能在一个经典项目中工作,但问题在于我正在研究一个框架。 所以mainVC将在客户端应用程序中,而第二个secondVCthirdVC在我的框架中,在一个单独的故事板中。 除了在我的代码中对它的引用mainVC ,我没有任何其他方式访问mainVC ,所以很遗憾,unwind segues不是一个选项。

我一直有这个完全相同的问题,我已经成功地通过将屏幕快照添加到secondVC.view的子视图来secondVC.view ,如下所示:

 if (self.presentedViewController.presentedViewController) { [self.presentedViewController.view addSubview:[[UIScreen mainScreen] snapshotViewAfterScreenUpdates:NO]]; } [self dismissViewControllerAnimated:YES completion:nil]; 

不漂亮,但它似乎工作。

注意:如果您的secondVC有一个导航栏,您需要在快照屏幕和将快照作为子视图添加到secondVC之间隐藏导航栏,否则快照将显示在导航栏下方,因此看似显示双导航在解雇动画期间的酒吧。 码:

 if (self.presentedViewController.presentedViewController) { UIView *snapshot = [[UIScreen mainScreen] snapshotViewAfterScreenUpdates:NO]; [self.presentedViewController.navigationController setNavigationBarHidden:YES animated:NO]; [self.presentedViewController.view addSubview:snapshot]; } [self dismissViewControllerAnimated:YES completion:nil]; 

我有同样的问题,我已经使用UnwindSegues修复了它。

基本上,您所要做的就是在ViewController中添加一个想要转换的IBAction Unwind Segue方法,然后在IB中将Exit操作连接到Unwind Segue方法。

例:

假设你有三个ViewControllers(VC1,VC2,VC3),你想从VC3转到VC1。

步骤1向VC1添加方法,如下所示:

 - (IBAction)unwindToVC1:(UIStoryboardSegue*)sender { } 

步骤2将 Interface Builder转到VC3并选择它。 然后按住CTRL键从VC图标拖动到“退出”图标,然后选择刚刚在VC1中添加的方法。

添加Unwind Segue

步骤3当仍然在IB中并且选择了VC3时,选择您的Unwind Segue并在Attributes Inspector中添加Segue标识符。

在此处输入图像描述在此处输入图像描述

步骤4转到VC3,您需要执行segue(或关闭VC)并添加以下内容:

 [self performSegueWithIdentifier:@"VC1Segue" sender:self];