【问题标题】:How to check viewcontroller is added in stack or not如何检查视图控制器是否添加到堆栈中
【发布时间】:2017-03-16 05:33:50
【问题描述】:

我有两个视图控制器。通过按下按钮使用下面的代码,我已经从一个视图导航到另一个视图。

 *let secondViewController = self.storyboard!.instantiateViewControllerWithIdentifier("NotificationController") as! NotificationController

self.navigationController!.pushViewController(secondViewController, animated: true)*

对于后面,我使用下面的代码在 bar 按钮上使用 bar button click for back。

 self.navigationController?.popViewControllerAnimated(true)

所以我的问题是,如果我不断地从一个视图转到另一个视图,那么它会添加到堆栈中。我只想显示另一个视图,当它已经添加到堆栈中以停止添加它。它只添加一次。

【问题讨论】:

标签: ios swift uiviewcontroller


【解决方案1】:

要检查导航堆栈是否包含特定类型的view controller,您可以使用:

if let viewControllers = self.navigationController?.viewControllers
{
    if viewControllers.contains(where: {
        return $0 is YourViewController
    })
    {
        //Write your code here
    }
}

要从导航堆栈中删除特定控制器,您需要对导航堆栈进行更改。

示例:

    if var viewControllers = self.navigationController?.viewControllers
    {
        for controller in viewControllers
        {
            if controller is UIViewController
            {
                viewControllers.removeElement(controller)
                self.navigationController?.viewControllers = viewControllers
            }
        }
    }

【讨论】:

  • Array 上没有 'removeElement()' 方法。但是您可以通过过滤 viewControllers 属性来执行相同的操作。请参阅我的答案以获取示例,并详细说明您的答案。干杯。
【解决方案2】:

对于 swift 4,您可以使用

 if let viewControllers = self.navigationController?.viewControllers {
       for vc in viewControllers {
            if vc.isKind(of: YourViewController.classForCoder()) {
                 print("It is in stack")
                 //Your Process
            }
       }
 }

【讨论】:

    【解决方案3】:

    针对 Swift 4.1 详细阐述 PGDev 的答案

    如何从UINavigationController 堆栈中删除特定的UIViewController 子类:

    /// Given 'nc' is a valid UINavigationController instance,
    /// removes all instances of MyViewController from the stack
    
    nc.viewControllers = nc.viewControllers.filter { !($0 is MyViewController) }
    

    把它作为一个扩展:

    extension UINavigationController
    {
        /// Given the kind of a (UIViewController subclass),
        /// removes any matching instances from self's
        /// viewControllers array.
    
        func removeAnyViewControllers(ofKind kind: AnyClass)
        {
            self.viewControllers = self.viewControllers.filter { !$0.isKind(of: kind)}
        }
    
        /// Given the kind of a (UIViewController subclass),
        /// returns true if self's viewControllers array contains at
        /// least one matching instance.
    
        func containsViewController(ofKind kind: AnyClass) -> Bool
        {
            return self.viewControllers.contains(where: { $0.isKind(of: kind) })
        }
    }
    

    用法:

    guard let nc = self.navigationController else { return }
    
    let exists = nc.containsViewController(ofKind: MyViewController.self)
    
    nc.removeAnyViewControllers(ofKind: MyViewController.self)
    

    顺便说一句,如果有人知道如何将 'kind' 限制在 UIViewController 的子类中,请大声说出来。

    【讨论】:

    • func containsViewController(ofKind kind: UIViewController.Type) -> Bool { return self.viewControllers.contains(where: { $0.isKind(of: kind) }) }
    【解决方案4】:

    这是检查它的代码。

    if let viewControllers = navigationController?.viewControllers {
        for viewController in viewControllers {
            // some process
            if viewController.isKindOfClass(ViewControllerClassName) {
                println("yes it is")
            }
        } 
    }
    

    【讨论】:

    • 添加时如何在栈中移除
    • vc.removeFromParentViewController- 使用这个方法
    • 如果你知道索引号,你也可以使用这个 self.navigationController?.viewControllers.removeAtIndex(vcIndex)
    • 您觉得这有帮助吗?
    • 当我再次从堆栈中移除时。它没有通过使用此代码添加到堆栈中。
    【解决方案5】:
    extension UINavigationController {
        public func hasViewController(ofKind kind: AnyClass) -> UIViewController? {
            return self.viewControllers.first(where: {$0.isKind(of: kind)})
        }
    }
    

    使用

    self.navigationController.hasViewController(ofKind: #ViewControllerName#.self)
    

    【讨论】:

      【解决方案6】:

      您可以通过以下code查看

      目标 - C

      NSArray * controllers = [self.navigationController viewControllers];
      
          for (int i = 0; i < [controllers count]; i++){
      
              UIViewController * controllerTest = [controllers objectAtIndex:i];
      
              if([controllerTest isKindOfClass:[YourController class]]){
                  NSLog(@"Class is available");
              }
      
          }
      

      斯威夫特 3.0

      if let viewControllers = self.navigationController?.viewControllers {
                  for viewController in viewControllers {
                      // some process
                      if viewController.isKindOfClass(YourController) {
                          print("Class is available")
                      }
                  } 
              }
      

      【讨论】:

      • 如何在类可用时删除或仅显示而不添加堆栈
      【解决方案7】:

      我们开始吧。

      这一行会给你一个 UIViewControllers 数组

      self.navigationController?.viewControllers

      现在你要做的是检查你的 viewControllerObject 是否存在?

      通过写这行

      if viewController.isKindOfClass(YourController){
      }
      

      这是一个完整的代码。

      if let viewControllers = self.navigationController?.viewControllers {
                  for viewController in viewControllers {
      
                      if viewController.isKindOfClass(YourController) {
                          print("Your controller exist")
                      }
             } 
      }
      

      当您在返回“ViewControllerA”时写下一行时,它将从导航堆栈中删除一个 ViewControllerB。

      self.navigationController?.popViewControllerAnimated(true)
      

      这与我们对堆栈进行的弹出操作类似,而导航控制器是一个堆栈。

      如果您有任何困惑,请告诉我。

      【讨论】:

        【解决方案8】:

        Swift 5(工作测试)。 检查视图控制器是否堆叠在导航中的更好方法是简单地询问视图控制器的可访问性。参见示例 下面。我使用这个 sn-p 回到以前的视图控制器。

            if self.navigationController?.accessibilityActivate() != nil {
                self.navigationController?.popViewController(animated: true)
            } else {
                self.dismiss(animated: true, completion: nil)
            }
        

        【讨论】:

          【解决方案9】:

          这是另一个独奏:

              guard let controllersInStack = navigationController?.viewControllers else { return }
              if let yourViewController = controllersInStack.first(where: { $0 is YourViewController }) {
                  // Do what you want with yourViewController
              }
          

          【讨论】:

            【解决方案10】:

            您只需检查视图控制器的 nibName 即可获得结果

            下面的这段代码将确保您不会在 navigatoinController 中再次添加一个 viewController,

                var VC = YourViewController
                var objVC = (storyboard.instantiateViewController(withIdentifier: "YourViewController"))
                
            if navigationController.viewControllers.contains(where: { (VC) -> Bool in
                        return objVC.nibName == VC.nibName
                    }){
                        for (i,controller) in navigationController.viewControllers.enumerated()
                        {
                            if controller.isKind(of: VC){
                                navigationController.viewControllers.remove(at: i)
                                navigationController.pushViewController(objVC, animated: false)
                            }
                        }
                    }else{navigationController.pushViewController(objVC, animated: false)}
            

            如果你只是想检查 viewController 是否在 NaviagtionController 中,那么试试这个:

            var checkForView = navigationController.viewControllers.contains(where: { (VC) -> Bool in
                        return objVC.nibName == VC.nibName
                    })
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2017-12-18
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2015-11-15
              • 2014-06-30
              相关资源
              最近更新 更多