54

我正在使用基于导航的应用程序。我将 First ViewController 推送到 Second ViewController 并从 Second ViewController 推送到 Third ViewController。现在我想从第三个 ViewController 弹出到第一个 ViewController。我正在使用下面的代码执行此任务,但我的应用程序崩溃了。

请任何机构给我一些适当的指导。我不能使用 pop 到 rootViewController,因为它是不同的 viewController。提前致谢...

在第三个 ViewControler 我写了这个:

FirstViewCtr *x=[[FirstViewCtr alloc] initWithNibName:@"FirstViewCtr" bundle:nil];
[self.navigationController popToViewController:x animated:NO];
4

16 回答 16

95

通过编写第一行,您可以获得所有视图控制器的索引,从第二行您将到达您的目的地。

NSArray *array = [self.navigationController viewControllers];

[self.navigationController popToViewController:[array objectAtIndex:2] animated:YES];
于 2010-06-12T09:15:58.343 回答
80

更安全的方法:

- (void)turnBackToAnOldViewController{

    for (UIViewController *controller in self.navigationController.viewControllers) {

        //Do not forget to import AnOldViewController.h
        if ([controller isKindOfClass:[AnOldViewController class]]) { 

            [self.navigationController popToViewController:controller
                                                  animated:YES];
            return;
        }
    }
}
于 2013-02-21T13:12:33.343 回答
20

快捷方式:

     let dashboardVC = navigationController!.viewControllers.filter { $0 is YourViewController }.first!
     navigationController!.popToViewController(dashboardVC, animated: true)
于 2015-12-21T13:59:16.617 回答
8

斯威夫特 4版本

if let viewController = navigationController?.viewControllers.first(where: {$0 is YourViewController}) {
      navigationController?.popToViewController(viewController, animated: false)
}

您可以根据需要指定另一个过滤器,.viewControllers.first例如,如果您有相同kind的视图控制器驻留在导航控制器中,那么您可以指定一个额外的检查,如下所示

  if let viewController = navigationController?.viewControllers.first(where: {
        if let current = $0 as? YourViewController {
             return current.someProperty == "SOME VALUE"
        }
       return false } ) {
            navigationController?.popToViewController(viewController, animated: false)
   }
于 2018-08-01T20:15:31.777 回答
6

通常从堆栈顶部执行此操作更为重要,因此:

- (void)popToLast:(Class)aClass
{
    for (int i=self.navigationController.viewControllers.count-1; i>=0; i--)
    {
        UIViewController *vc = self.navigationController.viewControllers[i];
        if ([vc isKindOfClass:aClass])
        {
            [self.navigationController popToViewController:vc animated:YES];
            break;
        }
    }
}

你这样称呼

popToLast:[SomeViewController class];
于 2013-09-04T09:57:12.277 回答
6
- (void) RetunToSpecificViewController{

   for (UIViewController *controller in self.navigationController.viewControllers)
    {
           if ([controller isKindOfClass:[AnOldViewController class]])
           {
            //Do not forget to import AnOldViewController.h

                       [self.navigationController popToViewController:controller
                                                             animated:YES];
                        break;
            }
    }
}
于 2015-04-28T07:41:55.750 回答
4
[self.navigationController popToViewController:[self.navigationController.viewControllers objectAtIndex:1] animated:YES];
于 2016-05-28T06:33:58.450 回答
2

快速安全的Swift 3版本:

if let vc = navigationController.viewControllers.filter({ $0 is SpecificViewControllerClass }).first {
  navigationController.popToViewController(vc, animated: true)
}
于 2017-06-07T15:06:16.717 回答
1

您的代码创建了一个从未被压入堆栈的视图的新实例,然后尝试弹回该控制器。

如果您要弹回根视图控制器,则可以使用popToRootViewControllerAnimated:

如果您要返回已知距离,则可以popViewControllerAnimated:多次调用。在您的示例中,这将是 2 个控制器以便调用。viewControllers您可以通过从末端查找控制器 2 并弹出它来做同样的事情。

上述建议是快速修复。一种最佳实践方案是将您想要返回的控制器传递给您推送的每个连续控制器。First 将自身传递给 second,second 将该引用传递给第三个,第三个 pop 传递给传递的引用,即 first。

实际上,您正在创建一个临时根控制器。您可以子类化UINavigationController并添加一个temporaryRoot属性和一个popToTemporaryRootViewControllerAnimated:方法,这些属性和方法会弹出到您的临时根目录并清除它。当第一次推送秒时,它也会将自己设置为临时根,这样堆栈中的每个控制器都不必传递引用。您将不得不添加一些额外的检查,以确保您永远不会在没有清除它的情况下弹出临时根目录。

于 2010-06-12T05:47:57.920 回答
1

经过大量努力,有人在 Swift 3.0 中创建了返回到特定视图控制器的快速扩展。

extension UINavigationController {

    func backToViewController(viewController: Swift.AnyClass) {

            for element in viewControllers as Array {
                if element.isKind(of: viewController) {
                    self.popToViewController(element, animated: true)
                break
            }
        }
    }
}

方法调用:

 self.navigationController?.backToViewController(viewController: YourViewController.self)
于 2017-05-08T12:17:14.210 回答
1

在Swift 3.0中实现和测试

以下是可用于导航到任何特定视图控制器的方法:

func poptoSpecificVC(viewController : Swift.AnyClass){
        let viewControllers: [UIViewController] = self.navigationController!.viewControllers
        for aViewController in viewControllers {
            if aViewController.isKind(of: viewController) {
                self.navigationController!.popToViewController(aViewController, animated: true)
                break;
            }
        }
    }

用法 :

self.poptoSpecificVC(viewController: createIntervalVC.self)
于 2017-07-17T14:15:48.997 回答
1

我认为这.filter({...}).first.first(where: {...}). 这也可以更精确地写成只针对 UIViewControllers。

extension UINavigationController {
    func popToController<T: UIViewController>(_ type: T.Type, animated: Bool) {
        if let vc = viewControllers.first(where: { $0 is T }) {
            popToViewController(vc, animated: animated)
        }
    }
    func popToControllerOrToRootControllerIfNotInTheStack<T: UIViewController>(_ type: T.Type, animated: Bool) {
        if let vc = viewControllers.first(where: { $0 is T }) {
            popToViewController(vc, animated: animated)
        } else {
            popToRootViewController(animated: animated)
        }
    }
}
于 2017-10-24T11:46:57.047 回答
1

为 Swift 3 更新:

用于下面的简单代码,用于弹出到特定的视图控制器;

 for vc in self.navigationController!.viewControllers as Array {
          if vc.isKind(of: YourViewControllerName) {
               self.navigationController!.popToViewController(vc, animated: true)
               break
          }
    }
于 2017-11-16T04:47:45.200 回答
0
for controller in self.navigationController!.viewControllers as Array {
        if controller.isKind(of: LoginVC.self) {
            _ =  self.navigationController!.popToViewController(controller, animated: true)
            break
        }
    }
于 2018-03-09T15:54:19.860 回答
0

将函数放入UIViewController 1 中。它检查特定是否UIViewController存在于UINavigationControllerthenpopToViewController或 elsepushViewController

func navigate(_ navVC: AnyClass, pushVC: UIViewController) {
    for obj in self.navigationController!.viewControllers {
        if obj.isMember(of: navVC) {
            self.navigationController!.popToViewController(obj, animated: true)
            return
        }
    }
    self.navigationController!.pushViewController(pushVC, animated: true)
}

采用

self.navigate(ViewController.self, pushVC: self.storyboard?.instantiateViewController(withIdentifier: "ViewController") as! ViewController)
于 2018-05-15T07:36:46.310 回答
0

i have answer here. This is 100% working code for Swift > 4.X

How can I pop specific View Controller in Swift

于 2019-07-30T06:07:42.927 回答