【问题标题】:Can i pop to Specific ViewController?我可以弹出到特定的 ViewController 吗?
【发布时间】:2011-03-02 22:29:19
【问题描述】:

我正在使用基于导航的应用程序。我将 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];

【问题讨论】:

    标签: iphone uinavigationcontroller popviewcontroller


    【解决方案1】:

    我在这里有答案。这是 Swift > 4.X

    的 100% 工作代码

    How can I pop specific View Controller in Swift

    【讨论】:

      【解决方案2】:

      Swift 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)
         }
      

      【讨论】:

        【解决方案3】:

        将函数放入UIViewController 1. 它检查特定UIViewController 是否存在于UINavigationController 然后popToViewControllerpushViewController

        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)
        

        【讨论】:

          【解决方案4】:
          for controller in self.navigationController!.viewControllers as Array {
                  if controller.isKind(of: LoginVC.self) {
                      _ =  self.navigationController!.popToViewController(controller, animated: true)
                      break
                  }
              }
          

          【讨论】:

            【解决方案5】:

            更安全的方法:

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

            【讨论】:

            • 比本地方法更安全?怎么样?
            • 本机方法是消息 popToViewController:animated,而不是您向消息提供参数的方式。我相信这个解决方案更安全,因为当你说 [array objectAtIndex:2] 时,你会自动假设 VC 的数量大于 2。如果不是这种情况,程序会崩溃,使用我的解决方案它会停止并且不会如果没有所需 VC 的实例,则崩溃。
            • 我认为您的方法确实比公认的解决方案@YunusNedimMehel 更好。无论如何,完全偏离主题,我认为那里不需要中断句
            • @oPi 不过还是有风险的,因为顶视图控制器会在弹出动画完成后释放(我猜是 0.3 秒?)。所以最好避免这种情况
            • @morroko 如果它不在堆栈上,则无法弹出。您可以推送它,也可以手动将其插入到 viewControllers 堆栈中(它是一个公共的、可读写的 NSArray 属性)
            【解决方案6】:

            为 Swift 3 更新:

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

             for vc in self.navigationController!.viewControllers as Array {
                      if vc.isKind(of: YourViewControllerName) {
                           self.navigationController!.popToViewController(vc, animated: true)
                           break
                      }
                }
            

            【讨论】:

              【解决方案7】:

              我认为.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)
                      }
                  }
              }
              

              【讨论】:

                【解决方案8】:

                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)
                

                【讨论】:

                  【解决方案9】:

                  快速安全的Swift 3版本:

                  if let vc = navigationController.viewControllers.filter({ $0 is SpecificViewControllerClass }).first {
                    navigationController.popToViewController(vc, animated: true)
                  }
                  

                  【讨论】:

                    【解决方案10】:

                    经过大量努力,有人在 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)
                    

                    【讨论】:

                      【解决方案11】:
                      [self.navigationController popToViewController:[self.navigationController.viewControllers objectAtIndex:1] animated:YES];
                      

                      【讨论】:

                        【解决方案12】:

                        快捷方式:

                             let dashboardVC = navigationController!.viewControllers.filter { $0 is YourViewController }.first!
                             navigationController!.popToViewController(dashboardVC, animated: true)
                        

                        【讨论】:

                          【解决方案13】:
                          - (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;
                                      }
                              }
                          }
                          

                          【讨论】:

                            【解决方案14】:

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

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

                            【讨论】:

                              【解决方案15】:

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

                              NSArray *array = [self.navigationController viewControllers];
                              
                              [self.navigationController popToViewController:[array objectAtIndex:2] animated:YES];
                              

                              【讨论】:

                              • 太棒了。 +1 ..辉煌。我现在在我的应用程序中使用它。
                              • 或者,对于一个班轮作弊的人:[self.navigationController popToViewController:[[self.navigationController viewControllers]objectAtIndex:2] animated:YES];
                              【解决方案16】:

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

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

                              如果您要返回已知距离,您可以多次致电popViewControllerAnimated:。在您的示例中,这将是 2 个控制器来调用。您可以通过在 viewControllers 中查找控制器 2 并从末尾弹出来执行相同的操作。

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

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

                              【讨论】:

                              • 我有 RootViewController,然后它被推入 FirstViewController,然后在 SecondViewController 之后,然后在 ThirdViewController 之后,当我到达 ThirdViewController 时,我需要直接弹出到 FirstViewController。
                              猜你喜欢
                              • 1970-01-01
                              • 2012-08-05
                              • 1970-01-01
                              • 2015-09-25
                              • 2023-01-11
                              • 2017-08-16
                              • 2020-04-08
                              • 2012-02-08
                              • 2013-11-14
                              相关资源
                              最近更新 更多