在 iOS 中推送视图控制器时难以绕过堆栈中的视图控制器

Posted

技术标签:

【中文标题】在 iOS 中推送视图控制器时难以绕过堆栈中的视图控制器【英文标题】:Having difficulty bypassing view controller in stack when pushing view controller in iOS 【发布时间】:2014-11-05 19:57:08 【问题描述】:

我正在开发一个应用程序,其中依次具有三个视图控制器:ViewControllerA、ViewControllerB 和 ViewControllerC。在某些情况下,我需要用户从 ViewControllerA 直接转到 ViewControllerC,但不幸的是,这样做时,在转换到 ViewControllerC 期间,ViewControllerB 会短暂出现在屏幕上,这是我不希望的。

这是我正在使用的代码:

VCA 内部:

ViewControllerB *vcB = [ViewControllerB new];
    ViewControllerC *vcC = [ViewControllerC new];
    vcB.rootViewController = self;
    [self.navigationController pushViewController:vcB animated:NO];
    [self.navigationController pushViewController:vcC animated:YES];

正如我上面提到的,上面的代码发生在 ViewControllerA 中,我能够到达 ViewControllerC,但不幸的是,ViewControllerB 在转换过程中会暂时显示。我做错了什么,我需要做些什么来解决这个问题?

【问题讨论】:

【参考方案1】:

简单。这是一些几乎正确的伪代码

NSMutableArray *vcStack = [NSMutableArray arrayWithArray:self.navigationController.viewControllers];
[vcStack addObject:vcB];
[vcStack addObject:vcC];
[self.navigationController setViewControllers:vcStack animated:YES];

显然,如果您不想要现有的视图堆栈,则可以将其扔掉并制作自己的数组,但这可能会导致动画出现故障。

查看 UINavigationController 的文档了解更多信息: https://developer.apple.com/library/ios/documentation/Uikit/reference/UINavigationController_Class/index.html#//apple_ref/occ/instm/UINavigationController/setViewControllers:animated:

【讨论】:

嗨,马特,非常感谢您的解决方案。您能解释一下为什么您的解决方案有效吗?我的问题是,当前堆栈与您正在创建的堆栈(即 vcStack)不一样,那么为什么这样可以工作,而使用以前的堆栈却不行? 嗨 syedfa - 我们创建 vcStack 的原因是您不能直接修改视图堆栈,因为 self.navigationController.viewControllers 是只读的。因此,您必须将指针复制到一个可变数组中,进行修改(在这一次中,添加两个 VC),然后一次性设置整个堆栈。这能回答你的问题吗? 并非如此。我想我的问题是,为什么要修改堆栈?为什么会出现这个问题,尤其是当我们以完全相同的顺序插入两个视图控制器时? UINavigationController 的架构方式,仅使用 pushViewController:animated: 需要在第二个调用开始之前完成第一个调用。这在 iOS8 上更为明显,因为在 iOS8 中,Apple 在推送过程中更改/添加了更多挂钩,因此现在您可以修改和更改处理推送和弹出的动画和手势。所以,为了解决这个问题,只显示两个 VC 的 1 个推送动画,我们必须修改堆栈,然后一次性提交更改。【参考方案2】:

您可以推送vcC,一旦vcC 完全显示在屏幕上,悄悄地修改堆栈以在vcA 之前插入vcB

ViewControllerB *vcB = [ViewControllerB new];
ViewControllerC *vcC = [ViewControllerC new];
[self.navigationController pushViewController:vcC animated:YES];

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^
    NSMutableArray *viewControllers = [self.navigationController.viewControllers mutableCopy];
    NSInteger indexOfC = [viewControllers indexOfObject:vcC];
    [viewControllers insertObject:vcB atIndex:indexOfC];
    [self.navigationController setViewControllers:viewControllers animated:NO];
);

【讨论】:

【参考方案3】:

需要直接从A跳到C吗?

那就用[self.navigationController pushViewController:vcC animated:YES];

也没有必要推动 B……或者你需要保持这个顺序?

【讨论】:

如果用户决定按下 C 上的后退按钮,那么是的,用户应该被带到 B。跳过是向前,而不是向后。 [self.navigationController addChildViewController:vcB] 然后推送到 C 这会在你的答案之前出现吗?所以它会是:[self.navigationController addChildViewController:vcB];然后 [self.navigationController pushViewController:vcC animated:YES]; ? 我试过了,不幸的是我根本没有离开 vcA。我正在调用代码块,但什么也没发生。

以上是关于在 iOS 中推送视图控制器时难以绕过堆栈中的视图控制器的主要内容,如果未能解决你的问题,请参考以下文章

Swift iOS - 如何打印导航堆栈中尚未推送的所有子视图控制器的列表

区分导致视图控制器被推送的用户操作

推送视图:在发生现有转换或演示时;导航堆栈不会更新

iOS – 在导航堆栈中显示一个视图控制器

iOS 应用程序在推送“动画”设置为“是”的视图控制器时崩溃,但在“动画”设置为“否”时工作正常

iOS - 如何推送到视图控制器并在返回时保持正确的“视图堆栈”