如何识别导航堆栈中的前一个视图控制器
Posted
技术标签:
【中文标题】如何识别导航堆栈中的前一个视图控制器【英文标题】:How to identify previous view controller in navigation stack 【发布时间】:2011-10-23 18:18:42 【问题描述】:我有两个单独的navigationcontrollers
,一个是RootViewController
A,另一个是RootViewController
B。
我可以将ViewController
C 推送到 A 或 B 的导航堆栈中。
问题:当我在ViewController
C 中时,如何知道我是在属于A 还是B 的堆栈中?
【问题讨论】:
为什么不直接在 C 上创建一个 previousViewController 属性,在推送 C 时设置它?还是在推送时从 A 或 B 向 C 提供所需的信息? @TerryWilcox ,'因为现在的关系可能非常复杂 【参考方案1】:更简洁的 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]
【讨论】:
【参考方案2】:您可以使用UINavigationController
的viewControllers
属性:
@property(nonatomic, copy) NSArray *viewControllers
讨论:根视图控制器在数组中的索引 0 处,后视图控制器在索引 n-2 处,顶部控制器在索引 n-1 处,其中 n 是数组中的项目数。
https://developer.apple.com/documentation/uikit/uinavigationcontroller
您可以使用它来测试根视图控制器(数组索引为 0 的那个)是视图控制器 A 还是 B。
【讨论】:
如何在 SWIFT 中将其作为字符串获取。(我是 swift 新手) @cyberboy 同样简单:使用var viewControllers: [UIViewController]
上一个视图控制器将位于viewControllers.last
@Burak viewControllers.last
有当前的视图控制器,为了获得以前的视图控制器,应该使用viewControllers[viewControllers.count-2]
【参考方案3】:
对于 swift 3,您可以这样做:
var backtoViewController:UIViewController!
for viewController in (self.navigationController?.viewControllers)!.reversed()
if viewController is NameOfMyDestinationViewController
backtoViewController = viewController
self.navigationController!.popToViewController(backtoViewController, animated: true)
您只需要将“NameOfMyDestinationViewController”替换为您要返回的viewController。
【讨论】:
【参考方案4】:我的扩展,swift 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
【讨论】:
【参考方案5】:作为UINavigationController
扩展:
extension UINavigationController
func previousViewController() -> UIViewController?
guard viewControllers.count > 1 else
return nil
return viewControllers[viewControllers.count - 2]
【讨论】:
【参考方案6】:使用 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]
【讨论】:
【参考方案7】:这是Prabhu Beeman's 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
【讨论】:
一些注意事项:reverse() 现在是 reversed() 并且 self.navigationController?.viewControllers 永远不会包含“self”视图控制器,所以 return stack.last 应该足够了【参考方案8】:Swift 2.2 的实现 - 将此添加到 UIViewController
扩展中。从某种意义上说是安全的,如果视图控制器是 rootvc 或不在导航控制器中,它将返回 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
【讨论】:
【参考方案9】:tjklemz 代码作为扩展的 Swift 实现:
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
【讨论】:
我已经发布了这个代码的修改版本,它在下面作为新的答案支持 Swift 3。【参考方案10】:因为死马喜欢被打:)
- (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];
【讨论】:
【参考方案11】:查找前一个视图控制器很简单。
在您的情况下,即您在 C 中并且您需要 B,[self.navigationController.viewControllers lastObject]
就是您想要的。
对于A来说,由于A是根视图控制器,只需将lastObject
替换为firstObject
即可获得。
【讨论】:
【参考方案12】:@tjklemz 代码的 Swift 实现:
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
【讨论】:
我怎样才能把它作为一个字符串..(我是 swift 新手) @cyberboy 你好!我不确定我是否理解你的问题。您想将 backViewController 描述作为字符串吗?如果是这样,您可以考虑println("backViewController is: \(backViewController.description)")
;这会给你一个类似“UINavigationController: 0x7fcea1d286b0”的描述,不是很清楚,但至少可以让你识别对象。正如我所说,我不确定你到底需要什么......【参考方案13】:
- (UIViewController *)backViewController
NSInteger myIndex = [self.navigationController.viewControllers indexOfObject:self];
if ( myIndex != 0 && myIndex != NSNotFound )
return [self.navigationController.viewControllers objectAtIndex:myIndex-1];
else
return nil;
【讨论】:
【参考方案14】:已接受答案的更通用实现:
- (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;
这将返回正确的“后视图控制器”,无论当前类在导航堆栈中的什么位置。
【讨论】:
【参考方案15】:这是接受的答案的实现:
- (UIViewController *)backViewController
NSInteger numberOfViewControllers = self.navigationController.viewControllers.count;
if (numberOfViewControllers < 2)
return nil;
else
return [self.navigationController.viewControllers objectAtIndex:numberOfViewControllers - 2];
【讨论】:
我建议将此作为类别添加到UIViewController
【参考方案16】:
访问viewControllers
属性的n-2
元素以访问父视图控制器。
获得该实例后,您可以通过记录NSStringFromClass()
函数的结果来检查其类型。或者,您可以在控制器 A 和 B 中保留一些 static const
标识符字符串,以及打印出字符串的 getter 函数。
【讨论】:
获取视图控制器当前索引的任何简单方法,或者我应该根据我的层次结构对它们进行硬编码。【参考方案17】:使用navigationController
方法检索它。见documentation on Apple's site。
navigationController 作为导航的父级或祖先 控制器。 (只读)
@property(非原子,只读,保留) UINavigationController *导航控制器
讨论 如果视图只返回一个导航控制器 控制器在其堆栈中。如果导航,则此属性为零 找不到控制器。
可用性适用于 ios 2.0 及更高版本。
【讨论】:
以上是关于如何识别导航堆栈中的前一个视图控制器的主要内容,如果未能解决你的问题,请参考以下文章