如何识别导航堆栈中的前一个视图控制器
我有2个独立的navigationcontrollers
RootViewController
,一个用RootViewController
A,另一个用RootViewController
B.
我能够将ViewController
C推送到A或B的导航堆栈上。
问题:当我在ViewController
C中时,如何知道我是否在属于A或B的堆栈中?
你可以使用UINavigationController
的viewControllers
属性:
@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是根视图控制器,所以你可以用firstObject
replacelastObject
来获得。
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] } }