如何识别导航堆栈中的前一个视图控制器

我有2个独立的navigationcontrollers RootViewController ,一个用RootViewController A,另一个用RootViewController B.

我能够将ViewController C推送到A或B的导航堆栈上。

问题:当我在ViewController C中时,如何知道我是否在属于A或B的堆栈中?

你可以使用UINavigationControllerviewControllers属性:

@property(nonatomic, copy) NSArray *viewControllers

讨论:根视图控制器位于数组中的索引0处,后视图控制器位于索引n-2,顶部控制器位于索引n-1处,其中n是数组中的项目数。

https://developer.apple.com/documentation/uikit/uinavigationcontroller

您可以使用它来testing根视图控制器(数组索引0处的视图控制器)是否为视图控制器A或B.

以下是接受的答案的实现:

 - (UIViewController *)backViewController { NSInteger numberOfViewControllers = self.navigationController.viewControllers.count; if (numberOfViewControllers < 2) return nil; else return [self.navigationController.viewControllers objectAtIndex:numberOfViewControllers - 2]; } 
 - (UIViewController *)backViewController { NSInteger myIndex = [self.navigationController.viewControllers indexOfObject:self]; if ( myIndex != 0 && myIndex != NSNotFound ) { return [self.navigationController.viewControllers objectAtIndex:myIndex-1]; } else { return nil; } } 

接受答案的更一般的实现:

 - (UIViewController *)backViewController { NSArray * stack = self.navigationController.viewControllers; for (int i=stack.count-1; i > 0; --i) if (stack[i] == self) return stack[i-1]; return nil; } 

这将返回正确的“后视图控制器”,而不pipe当前类在导航堆栈上的什么位置。

Swift实现tjklemz代码作为扩展:

 extension UIViewController { func backViewController() -> UIViewController? { if let stack = self.navigationController?.viewControllers { for(var i=stack.count-1;i>0;--i) { if(stack[i] == self) { return stack[i-1] } } } return nil } } 

这里有一个修改后的版本的Prabhu Beeman的 Swift代码,它可以支持Swift 3:

 extension UIViewController { func backViewController() -> UIViewController? { if let stack = self.navigationController?.viewControllers { for i in (1..<stack.count).reverse() { if(stack[i] == self) { return stack[i-1] } } } return nil } } 

访问viewControllers属性的n-2元素以访问父视图控制器。

一旦你有了这个实例,你可以通过loggingNSStringFromClass()函数的内容来检查它的types。 或者你可以在控制器A和B中保留一些static const标识符string,以及打印出string的getter函数。

快速执行@tjklemz代码:

 var backViewController : UIViewController? { var stack = self.navigationController!.viewControllers as Array for (var i = stack.count-1 ; i > 0; --i) { if (stack[i] as UIViewController == self) { return stack[i-1] as? UIViewController } } return nil } 

作为UINavigationController扩展:

 extension UINavigationController { func previousViewController() -> UIViewController? { guard viewControllers.count > 1 else { return nil } return viewControllers[viewControllers.count - 2] } } 

使用navigationController方法来检索它。 请参阅Apple网站上的文档 。

navigationController导航控制器的父代或祖代。 (只读)

@property(nonatomic,只读,保留)UINavigationController * navigationController

Discussion如果视图控制器在其堆栈中,则仅返回导航控制器。 如果找不到导航控制器,则该属性为零。

Availability在iOS 2.0及更高版本可用。

因为死马享受被殴打:)

 - (UIViewController *)previousViewController { NSArray *vcStack = self.navigationController.viewControllers; NSInteger selfIdx = [vcStack indexOfObject:self]; if (vcStack.count < 2 || selfIdx == NSNotFound) { return nil; } return (UIViewController *)[vcStack objectAtIndex:selfIdx - 1]; } 

find以前的视图控制器很简单。

在你的情况,即,你在C,你需要B, [self.navigationController.viewControllers lastObject]是你想要的。

对于A来说,因为A是根视图控制器,所以你可以用firstObjectreplacelastObject来获得。

Swift 2.2的实现 – 将其添加到UIViewController扩展中。 如果viewcontroller是rootvc,或者不在navigationcontroller中,它将返回nil

 var previousViewController: UIViewController? { guard let viewControllers = navigationController?.viewControllers else { return nil } var previous: UIViewController? for vc in viewControllers{ if vc == self { break } previous = vc } return previous } 

用Swift使用警卫。

 extension UIViewController { func getPreviousViewController() -> UIViewController? { guard let _ = self.navigationController else { return nil } guard let viewControllers = self.navigationController?.viewControllers else { return nil } guard viewControllers.count >= 2 else { return nil } return viewControllers[viewControllers.count - 2] } } 

我的扩展,迅速3

 extension UIViewController { var previousViewController: UIViewController? { guard let controllers = navigationController?.viewControllers, controllers.count > 1 else { return nil } switch controllers.count { case 2: return controllers.first default: return controllers.dropLast(2).first } } } 

对于swift 3你可以这样做:

 var backtoViewController:UIViewController! for viewController in (self.navigationController?.viewControllers)!.reversed() { if viewController is NameOfMyDestinationViewController { backtoViewController = viewController } } self.navigationController!.popToViewController(backtoViewController, animated: true) 

你只需要用viewControllerreplace你想返回的“NameOfMyDestinationViewController”即可。

一个更简洁的Swift约束:

 extension UIViewController { var previousViewController: UIViewController? { guard let nav = self.navigationController, let myIdx = nav.viewControllers.index(of: self) else { return nil } return myIdx == 0 ? nil : nav.viewControllers[myIdx-1] } } 
  • NSUserDefaults – 如何判断一个密钥是否存在
  • UICollectionView的dynamic单元格宽度取决于标签宽度
  • 目标C:块与select器与协议
  • Swift中Objective-C id的等价物是什么?
  • 我怎样才能将一个int转换为NSString?
  • 什么时候视图(或图层)需要离屏渲染?
  • 有最大CGFloat值的常量吗?
  • 为什么Emacs / Vim / Textmate? Xcode不够好吗?
  • Swift中的只读和非计算variables属性
  • 格式错误或损坏的AST文件
  • 为UIAlertAction编写处理程序