【问题标题】:Skip/Add a View Controller in Navigation Stack在导航堆栈中跳过/添加视图控制器
【发布时间】:2015-11-15 02:25:00
【问题描述】:

我在导航控制器中嵌入了三个视图控制器。我想从 VC1 转到 VC3,以便在 VC3 中,导航项的后退按钮会将用户定向到 VC2 而不是 VC1。我认为这应该通过在创建 VC3 时将 VC2 添加到 VC1 和 VC3 之间的导航堆栈或通过跳过第二个视图控制器来完成。

我试过这个:

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if let identifier = segue.identifier {
        switch identifier {
        case "JumpToThirdVCSegue":
            if let secondvc = segue.destinationViewController as? SecondViewController {
                secondvc.performSegueWithIdentifier("ThirdVCSegue", sender: self)
            }
        default: break
        }
    }
}

但我无法让它工作。当 View Controller 尚未打开时,可能无法执行 segue?

在导航堆栈中间跳过视图控制器/添加视图控制器的最佳方法是什么?我希望这可以帮助您理解我正在尝试做的事情:

【问题讨论】:

    标签: ios swift uinavigationcontroller


    【解决方案1】:

    这样的事情应该可以工作:

        self.navigationController?.pushViewController(viewController2, animated: true)
        self.navigationController?.pushViewController(viewController3, animated: true)
    

    编辑:

    如果您想在不被用户注意的情况下推送第二个视图控制器,您需要在推送第三个视图控制器后将其添加到导航控制器。这可以通过实现UINavigationControllerDelegate 来完成。您可以将第二个视图控制器存储在一个变量中,并将其插入到委托方法中的导航控制器层次结构中。您的主视图控制器将如下所示:

    class MyViewController: UIViewController, UINavigationControllerDelegate {
    
        var viewControllerToInsertBelow : UIViewController?
    
        override func viewDidLoad() {
            super.viewDidLoad()
            self.navigationController?.delegate = self
        }
    
        func pushTwoViewControllers() {
            if let viewController2 = self.storyboard?.instantiateViewControllerWithIdentifier("id1"),
                let viewController3 = self.storyboard?.instantiateViewControllerWithIdentifier("id2") { //change this to your identifiers
                    self.viewControllerToInsertBelow = viewController2
                    self.navigationController?.pushViewController(viewController3, animated: true)
            }
        }
    
        //MARK: - UINavigationControllerDelegate
        func navigationController(navigationController: UINavigationController, didShowViewController viewController: UIViewController, animated: Bool) {
            if let vc = viewControllerToInsertBelow {
                viewControllerToInsertBelow = nil
                let index = navigationController.viewControllers.indexOf(viewController)!
                navigationController.viewControllers.insert(vc, atIndex: index)
            }
        }
    
    }
    

    【讨论】:

    • 这首先显示 VC2,然后立即将 VC3 推到它上面,这不是我想要的,因为 VC2 应该“出现”在 1 和 3 之间。也许这可以改变工作不过。
    • self.navigationController?.pushViewController(viewController2, animated: false)
    【解决方案2】:
    if var navstack = navigationController?.viewControllers{
                        navstack.append(contentsOf: [vc1,vc2])
                        navigationController?.setViewControllers(navstack, animated: true)
                    }
    

    效果很好

    【讨论】:

    • 虽然此代码可能会回答问题,但提供有关此代码为何和/或如何回答问题的额外上下文可提高其长期价值。
    • 它已最小化并从上面检查代码。对不起,如果我有可能在 cmets 中回答有问题,我会这样做。我希望你不会因为我的行为而生我的气)
    【解决方案3】:

    编辑:使用 swift 和 segues,这应该可以工作:

    override func performSegueWithIdentifier(identifier: String?, sender: AnyObject?) {
        super.performSegueWithIdentifier(identifier, sender: sender);
    
        if identifier == "JumpToThirdVCSegue" {
            // now the vc3 was already pushed on the navigationStack
            var navStackArray : [AnyObject]! = self.navigationController!.viewControllers
            // insert vc2 at second last position
            navStackArray.insert(viewController2, atIndex: navStackArray.count - 2)
            // update navigationController viewControllers
            self.navigationController!.setViewControllers(navStackArray, animated:false)
        }
    }
    

    所以你重写了 VC1 中的 performSegueWithIdentifier 以便在实际执行到 VC3 的 segue 时更改导航堆栈(并且不仅仅是在准备中)。 这假设您想在 VC1 中处理这个特殊的导航逻辑。

    【讨论】:

      【解决方案4】:

      你可以使用方法

      func setViewControllers(_ viewControllers: [UIViewController], animated: Bool)

      这是解决 UIViewController 跳过问题的文档 (link)。 只需将所有需要的UIViewControllers 传递给它(按导航顺序),最后一个将成为当前活动的UIViewController(如果它已经不是活动的)。

      【讨论】:

      • 完美答案。简短易懂。
      【解决方案5】:

      我的解决方案是保留一个 BOOL 属性,当你应该跳到第三和什么时候不跳过,比如在 VC2 中声明“shouldSkip”,这样如果你在下面的准备 segue 中设置它,你可以按照 VC2 中的操作

      override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
          if let identifier = segue.identifier {
              switch identifier {
              case "JumpToThirdVCSegue":
                  secondvc.shouldSkip=true
      
                  }
              default: break
              }
          }
      }
      

      然后在 viewDidload VC2 中,你应该检查这个 BOOL,如果它是真的并执行 segue,如果不是就继续 只要不需要那种跳过,你也可以通过传递

      【讨论】:

        【解决方案6】:

        根据MarkHim 的回答,当我导航回插入的视图控制器时出现黑屏,因此我想出了以下解决方案。

        顺便说一句 - 我想将新的视图控制器直接插入到我刚刚插入的视图控制器下,因此使用 navStack.count - 1 而不是 navStack - 2

        这是我的解决方案:

        override func performSegue(withIdentifier identifier: String, sender: Any?) {
            super.performSegue(withIdentifier: identifier, sender: sender)
        
            if identifier == "JumpToThirdViewControllerSegue",
            let navController = navigationController { // unwrap optional
        
                // initialize the view controller you want to insert
                let storyboard = UIStoryboard(name: "Main", bundle: nil)
                let viewControllerToInsert = storyboard.instantiateViewController(
                    withIdentifier: "SecondVC") as! SecondViewController
        
                // set any passed properties
                viewControllerToInsert.passedProperty = propertyToPass
        
                // create an object using the current navigation stack
                var navStackArray: [UIViewController]! = navController.viewControllers
        
                // insert the newly initialized view controller into the navStackArray
                navStackArray.insert(viewControllerToInsert, at: navStackArray.count - 1)
        
                // replace the current navigation stack with the one you just
                // inserted your view controller in to
                navController.setViewControllers(navStackArray, animated: false)
            }
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-05-17
          • 2012-05-04
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多