如何从导航控制器一次弹出两个视图?
Posted
技术标签:
【中文标题】如何从导航控制器一次弹出两个视图?【英文标题】:How do I pop two views at once from a navigation controller? 【发布时间】:2012-01-04 10:26:42 【问题描述】:我想将导航堆栈上的第三个视图弹回第一个视图。
我知道如何一次弹出一个视图:
[self.navigationController popViewControllerAnimated:YES];
但是我如何同时做两个呢?
【问题讨论】:
元评论:@lubilis 一直回答是最好的。评分最高的答案在当时还不错,但不再相关。 【参考方案1】:使用简单的 UINavigationController 扩展:
extension UINavigationController
func popViewControllers(_ count: Int)
guard viewControllers.count > count else return
popToViewController(viewControllers[viewControllers.count - count - 1], animated: true)
【讨论】:
【参考方案2】:斯威夫特 4:
func popViewControllerss(popViews: Int, animated: Bool = true)
if self.navigationController!.viewControllers.count > popViews
let vc = self.navigationController!.viewControllers[self.navigationController!.viewControllers.count - popViews - 1]
self.navigationController?.popToViewController(vc, animated: animated)
那就用这个方法
self.popViewControllerss(popViews: 2)
【讨论】:
好一个,我在找什么。谢谢你。【参考方案3】:这里有两个UINavigationController
扩展可以解决您的问题。我建议使用第一个弹出到特定类的 UIViewController
的:
extension UINavigationController
func popToViewController(ofClass: AnyClass, animated: Bool = true)
if let vc = viewControllers.filter($0.isKind(of: ofClass)).last
popToViewController(vc, animated: animated)
func popViewControllers(viewsToPop: Int, animated: Bool = true)
if viewControllers.count > viewsToPop
let vc = viewControllers[viewControllers.count - viewsToPop - 1]
popToViewController(vc, animated: animated)
并像这样使用它:
// pop to SomeViewController class
navigationController?.popToViewController(ofClass: SomeViewController.self)
// pop 2 view controllers
navigationController?.popViewControllers(viewsToPop: 2)
【讨论】:
对于 Swift(选项 1),您可以将两个removeLast
替换为 removeLast(2)
。
调用控制器生命周期的方法呢? DidAppear 等
(Swift 4) 您在这一行中缺少括号 let vc = viewControllers[viewControllers.count - viewsToPop + 1]
,为了正常工作,您需要将其替换为:let vc = viewControllers[viewControllers.count - (viewsToPop + 1)]
或 let vc = viewControllers[viewControllers.count - viewsToPop - 1]
@MMiroslav 你是对的。我已经更新了我的答案。谢谢/Hvala ;)
我在下面发布我的答案后,此答案已更新。基本上是我的代码的副本^_^【参考方案4】:
在 Swift 3 中, 你可以像这样从导航控制器中弹出一个、两个或多个视图控制器
let viewControllers = self.navigationController!.viewControllers as [UIViewController]
for aViewController:UIViewController in viewControllers
if aViewController.isKind(of: FromWhereYouWantToGoController.self)
_ = self.navigationController?.popToViewController(aViewController, animated: true)
这里 FromWhereYouWantToGoController 是目标控制器。希望能帮助到你。
【讨论】:
【参考方案5】:您可以使用 UIViewControllers 的堆栈。 1. 获取栈中所有视图控制器的数组。 2.遍历整个数组,找到想要的viewController 通过匹配类类型。 3. 弹出 viewController。
func popToSpecificViewC
let viewControllers: [UIViewController] = self.navigationController!.viewControllers as [UIViewController];
for viewController:UIViewController in viewControllers
if viewController.isKind(of: WelcomeViewC.self)
_ = self.navigationController?.popToViewController(viewController, animated: true)
【讨论】:
【参考方案6】:Swift 2 - xCode 7.3
这可能是弹出 UIViewControllers 的一个非常有用的扩展:
extension UINavigationController
func popToViewControllerOfType(classForCoder: AnyClass)
for controller in viewControllers
if controller.classForCoder == classForCoder
popToViewController(controller, animated: true)
break
func popViewControllers(controllersToPop: Int, animated: Bool)
if viewControllers.count > controllersToPop
popToViewController(viewControllers[viewControllers.count - (controllersToPop + 1)], animated: animated)
else
print("Trying to pop \(controllersToPop) view controllers but navigation controller contains only \(viewControllers.count) controllers in stack")
【讨论】:
这需要更多的支持......我正要写那个扩展。我会用你的谢谢;) @n13 这怎么比budidino的回答好? 使用扩展可以使代码更简洁。您可以采用 budidino 的答案并对其进行扩展,但这可以节省您的精力。此答案还检查错误情况,并优雅地处理错误(例如,尝试弹出比您拥有的更多) 我喜欢这个答案。让我重新思考并更新我发布的答案。我让我的代码弹出到 viewControllers 数组中搜索到的类的最后一个实例,因为这可能是所需的行为。【参考方案7】:[self.navigationController popToViewController:[self.navigationController.viewControllers objectAtIndex:1] animated:YES];
objectAtIndex:1 --> 你可以传递你想要弹出的任何索引
【讨论】:
谢谢你的诡计,我正要以错误的方式做。【参考方案8】:我在这里没有看到这个答案。如果您只想弹出一些(不是一直到根目录),您可以遍历 self.navigationController.viewControllers 检查类类型,或者如果您有参考使用:
for (UIViewController *aViewController in self.navigationController.viewControllers)
if ([aViewController isKindOfClass:[SMThumbnailViewController class]])
[self.navigationController popToViewController:aViewController animated:YES];
【讨论】:
【参考方案9】:Swift 版本(Swift 1.2 / Xcode 6.3.1) 弹出两次或更多次
var viewControllers = self.navigationController?.viewControllers
viewControllers?.removeLast()
viewControllers?.removeLast()
self.navigationController?.setViewControllers(viewControllers, animated: true)
或
var viewControllers = self.navigationController?.viewControllers
var viewsToPop = 2
var end = (viewControllers?.count)!
var start = end - viewsToPop
viewControllers?.removeRange(Range<Int>(start: start, end: end))
self.navigationController?.setViewControllers(viewControllers, animated: true)
【讨论】:
【参考方案10】://viewIndex = 1;
//viewIndex = 2;
//viewIndex = 3;
// **[viewControllers objectAtIndex: *put here your viewindex number*]
NSArray *viewControllers = [self.navigationController viewControllers];
[self.navigationController popToViewController:[viewControllers objectAtIndex:viewIndex] animated:NO];
【讨论】:
【参考方案11】:您也可以尝试在导航控制器堆栈之间跳转
NSMutableArray *allViewControllers = [NSMutableArray arrayWithArray:[self.navigationController viewControllers]];
for (UIViewController *aViewController in allViewControllers)
if ([aViewController isKindOfClass:[RequiredViewController class]])
[self.navigationController popToViewController:aViewController animated:NO];
【讨论】:
imo 这是迄今为止最好的方法,但您应该使用 self.navigationcontroller 引用您的 uinavigation 控制器 我同意,如果用户想将堆栈弹出回某个视图控制器,这是最好的解决方案。假设您不知道哪个视图控制器,您仍然可以实现一个系统,您可以在其中指定要从堆栈中弹出多少视图控制器并使用 objectAtIndex:(allViewControllers.count - 从 allViewControllers 数组中获取目标视图控制器1 - 数量)。 -1 因为数组当然是从零开始的。 在遍历原始 navigator->viewControllers 数组时也有效(无需将其转换为可变数组) 注意!这将从开始-> 到结束迭代堆栈,要完全正确,您应该反转堆栈。因为如果你有几个相同类型的 VC,你会在堆栈中以错误的顺序移除错误的 VC。【参考方案12】:您可以使用popToRootViewControllerAnimated
弹出到“根”(第一个)视图控制器:
[self.navigationController popToRootViewControllerAnimated:YES];
// If you want to know what view controllers were popd:
// NSArray *popdViewControllers = [self.navigationController popToRootViewControllerAnimated:YES];
UINavigationController
Reference:
弹出堆栈上除根视图控制器之外的所有视图控制器并更新显示。
返回值 从堆栈中弹出的视图控制器数组。
【讨论】:
哈,不敢相信我花了这么长时间才找到这么简单的答案,谢谢! Swift 3: self.navigationController?.popToRootViewController(animated:true); 正是我想要的!【参考方案13】: NSMutableArray *newStack = [NSMutableArray arrayWithArray:[self.navigationController viewControllers]];
[newStack removeLastObject];
[newStack removeLastObject];
[self.navigationController setViewControllers:newStack animated:YES];
【讨论】:
【参考方案14】:这是我用来返回 X ViewControllers 的一个小函数:
-(void)backMultiple:(id)data
int back = 2; //Default to go back 2
int count = [self.navigationController.viewControllers count];
if(data[@"count"]) back = [data[@"count"] intValue];
//If we want to go back more than those that actually exist, just go to the root
if(back+1 > count)
[self.navigationController popToRootViewControllerAnimated:YES];
//Otherwise go back X ViewControllers
else
[self.navigationController popToViewController:[self.navigationController.viewControllers objectAtIndex:count-(back+1)] animated:YES];
【讨论】:
【参考方案15】:你也可以试试这个:-
[self.navigationController popToViewController:yourViewController animated:YES];
【讨论】:
【参考方案16】:您可以传递初始视图控制器(您想要返回的那个),然后在最后一个视图中调用此行:
[self.navigationController popToViewController:yourInitialViewController animated:YES];
L.
【讨论】:
【参考方案17】:如果您只想一次弹出 2,因为您的 rootViewController 是(方式)“更深”,那么 2 您可以考虑向 UIviewController 添加一个类别,例如:
UINavigationController+popTwice.h
#import <UIKit/UIKit.h>
@interface UINavigationController (popTwice)
- (void) popTwoViewControllersAnimated:(BOOL)animated;
@end
UINavigationController+popTwice.m
#import "UINavigationController+popTwice.h"
@implementation UINavigationController (popTwice)
- (void) popTwoViewControllersAnimated:(BOOL)animated
[self popViewControllerAnimated:NO];
[self popViewControllerAnimated:animated];
@end
在您的实现中的某处导入类别 #import "UINavigationController+popTwice.h"
并使用这行代码一次弹出 2 个控制器:
[self.navigationController popTwoViewControllersAnimated:YES];
不是很好吗? :)
【讨论】:
如果需要弹出三个视图,你会写“UINavigationController+popThrice.m”?????? 你可以传入一个参数来表示要弹出的视图控制器的数量,然后包装 [self popViewControllerAnimated:NO];在一个 for 循环中,count-1。 这不是正确的方法,如果你想把 2,3,... 任何控制器循环识别它然后使用 [self.navigationController popToViewControllerAnimated:YES];。上面提到的这个是非常糟糕的编码,可能会显示闪烁的 UI 和糟糕的用户体验。【参考方案18】:你可以弹回根视图控制器
[self.navigationController popToRootViewControllerAnimated:YES];
或者,如果您要弹出的视图不是第一个,则需要在上一个视图的 viewWillAppear 中再次弹出
【讨论】:
以上是关于如何从导航控制器一次弹出两个视图?的主要内容,如果未能解决你的问题,请参考以下文章