我有类似的问题,我的“模态转场链”不受限制。我同意下面关于为不同事物设计的模态转场的答案和评论中的论点,但我喜欢模态转场的“水平翻转”动画,我找不到更简单的方法来复制它们......总的来说,我使用为一件事设计的东西来实现另一件事(例如链接模态控制器)没有任何问题。重复的“部分卷曲”动画也可以应用于某些应用程序中的某些场景。
所以我将模态控制器的堆栈实现为控制器的一个属性:
@interface ModalViewController : UIViewController
@property (nonatomic, retain) NSMutableArray *modalControllers;
@end
当执行第一个模态segue时,堆栈在非模态控制器的prepareForSegue方法中创建:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:@"modalSegue"]) {
ModalViewController *controller =
(ModalViewController *)[segue destinationViewController];
controller.modalControllers = [NSMutableArray arrayWithObject: controller];
}
}
当一个模态控制器移动到另一个模态控制器时,目的地被添加到堆栈中(在 ModalViewCotroller 的方法中)
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:@"modalSegue"]) {
ModalViewController *destController =
(ModalViewController *)[segue destinationViewController];
// add destination controller to stack
destController.modalControllers = _modalControllers;
[destController.modalControllers addObject: destController];
}
}
一次解除整个堆栈是最棘手的部分 - 你不能在下一个完成解除之前解除前一个控制器,所以循环不起作用,只有递归块才能做到这一点,避免内存泄漏是最棘手的(我还没有检查它,但我依靠这个):
- (IBAction)dismissAllModalControllers: (id)sender
{
// recursive block that dismisses one auth controller
// all these dances are to avoid leaks with ARC
typedef void (^voidBlockType)();
__block void (^dismissController) ();
voidBlockType __weak dismissCopy = ^void(void) {
dismissController();
};
dismissController = ^void(void) {
int count = [_modalControllers count];
if (count > 0) {
// get last controller
UIViewController *controller =
(UIViewController *)[_modalControllers lastObject];
// remove last controller
[_modalControllers removeLastObject];
// dismiss last controller
[controller
// the first controller in chain is dismissed with animation
dismissViewControllerAnimated: count == 1 ? YES : NO
// on completion call the block that calls this block recursively
completion: dismissCopy];
}
};
// this call dismisses all modal controllers
dismissController();
}