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

79

我有两个独立的navigationcontrollers,一个带有RootViewController A,另一个带有RootViewController B。

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

问题: 当我在ViewController C中时,如何确定我是否在属于A还是B的堆栈中?


7
在C中创建一个previousViewController属性,并在推出C时进行设置,或者在推出C时给它来自A或B的所需信息,这样为什么不行? - Terry Wilcox
1
@TerryWilcox,因为关系现在可能非常复杂。 - Vyacheslav
17个回答

107
你可以使用UINavigationControllerviewControllers属性:

@property(nonatomic, copy) NSArray *viewControllers

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

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

你可以使用这个来测试根视图控制器(数组索引为0的那个)是视图控制器A还是B。


我该如何在SWIFT中将其作为字符串获取?(我是SWIFT的新手) - M_R_K
@cyberboy 就像这样简单:使用 var viewControllers: [UIViewController] - NerdyTherapist
1
上一个视图控制器将会在 viewControllers.last - Burak
@Burak viewControllers.last 表示当前视图控制器,要获取上一个视图控制器,应该使用 viewControllers[viewControllers.count-2] - Ganpat

105

这是已被接受答案的实现:

- (UIViewController *)backViewController
{
    NSInteger numberOfViewControllers = self.navigationController.viewControllers.count;

    if (numberOfViewControllers < 2)
        return nil;
    else
        return [self.navigationController.viewControllers objectAtIndex:numberOfViewControllers - 2];
}

20
我建议将此添加为 UIViewController 的一个类别。 - MaxGabriel

29
- (UIViewController *)backViewController
{
    NSInteger myIndex = [self.navigationController.viewControllers indexOfObject:self];

    if ( myIndex != 0 && myIndex != NSNotFound ) {
        return [self.navigationController.viewControllers objectAtIndex:myIndex-1];
    } else {
        return nil;
    }
}

12

更通用的实现方法:

- (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;
}

无论当前类在导航堆栈中的位置如何,这将返回正确的“后退视图控制器(back view controller)”。


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。 - Cin316

9
这是一份修改过的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
    }
}

一些注意事项:reverse()现在是reversed(),而self.navigationController?.viewControllers从不包含"self"视图控制器,因此返回stack.last就足够了。 - Kappe

5
作为一个 UINavigationController 的扩展:
extension UINavigationController {

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

}

3

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

一旦您获得该实例,可以通过记录NSStringFromClass()函数输出的内容来检查其类型。或者您可以在控制器A和B中保留一些static const标识符字符串和一个获取函数来打印该字符串。


有没有一种简单的方法来获取视图控制器的当前索引,或者我应该根据我的层次结构硬编码它们? - HpTerm

2

Swift实现@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
    }

我该如何将其作为字符串获取?(我是Swift的新手) - M_R_K
@cyberboy 你好!我不确定我理解你的问题。你想将backViewController的描述作为字符串获取吗?如果是这样,你可以考虑使用println("backViewController is: \(backViewController.description)"); 这会给你一个类似于“UINavigationController: 0x7fcea1d286b0”的描述,虽然不是很清晰,但至少能让你识别出对象。就像我所说的,我不确定你需要什么… - cdf1982

1

因为死马喜欢被打 :)

- (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];
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接