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

时间:2011-08-10 04:07:04

标签: objective-c ios uiviewcontroller uinavigationcontroller

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

我可以将ViewController C推到A或B的导航堆栈上。

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

17 个答案:

答案 0 :(得分:106)

您可以使用UINavigationController的{​​{1}}属性:

  

viewControllers

     

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

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

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

答案 1 :(得分:102)

以下是接受答案的实施:

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

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

答案 2 :(得分:28)

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

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

答案 3 :(得分:11)

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

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

无论当前类在导航堆栈中的哪个位置,都将返回正确的“后视图控制器”。

答案 4 :(得分:9)

这是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
    }
}

答案 5 :(得分:9)

快速实施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
    }
}

答案 6 :(得分:3)

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

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

答案 7 :(得分:3)

作为UINavigationController扩展程序:

extension UINavigationController {

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

}

答案 8 :(得分:2)

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

答案 9 :(得分:1)

使用navigationController方法检索它。请参阅documentation on Apple's site

  

navigationController 作为导航的父级或祖先级   控制器。 (只读)

     

@property(非原子,只读,保留)UINavigationController   * navigationController

     

讨论仅在视图中返回导航控制器   控制器在其堆栈中。如果是导航,此属性为零   无法找到控制器。

     

可用性适用于iOS 2.0及更高版本。

答案 10 :(得分: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];
}

答案 11 :(得分:0)

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
}

答案 12 :(得分:0)

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

答案 13 :(得分:0)

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

在您的情况下,即您在C中并且您需要B,[self.navigationController.viewControllers lastObject]就是您想要的。

对于A,由于A是根视图控制器,因此您只需将lastObject替换为firstObject即可获得。

答案 14 :(得分:0)

我的扩展名,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
        }
    }
}

答案 15 :(得分:0)

for swift 3 你可以这样做:

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

你只需要替换&#34; NameOfMyDestinationViewController&#34;通过viewController你想要返回。

答案 16 :(得分:0)

更简洁的斯威夫特暗示:

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