在 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 - 如何打印导航堆栈中尚未推送的所有子视图控制器的列表