【问题标题】:Swift 3 - Push segue to navigation controllerSwift 3 - 将 segue 推送到导航控制器
【发布时间】:2016-10-19 17:59:47
【问题描述】:

在我的故事板中,我有一个视图控制器,还有一个导航控制器和另一个名为 HistoryController 的视图控制器。 Navigation Controller 和 HistroyController 有关系“根视图控制器”

我的第一个视图控制器上有一个按钮,并且该按钮有一个推送到导航控制器的按钮。

我在第一个视图控制器中有这段代码来准备转场:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {

        if let viewController = segue.destination as? HistoryController {
            viewController.detailItem = barcodeInt as AnyObject
        }

    }

我的问题是当我运行我的代码并按下我的第一个控制器中的按钮时,我收到此错误:

Could not find a navigation controller for segue 'HistorySegue'. Push segues can only be used when the source controller is managed by an instance of UINavigationController.'

我的问题是,为什么会出现此错误,我该如何解决?

我已经尝试了以下

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if let navVC = segue.destinationViewController as? UINavigationController{
            if let historyVC = navVC.viewControllers[0] as? HistoryController{
                historyVC.detailItem = barcodeInt as AnyObject
            }
        }
    }

我也试过

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if let nav = segue.destination as? UINavigationController {
        if let vc = nav.visibleViewController as? HistoryController {
            vc.detailItem = barcodeInt as AnyObject
        }
    }
}

我仍然得到同样的错误:

Could not find a navigation controller for segue 'HistorySegue'. Push segues can only be used when the source controller is managed by an instance of UINavigationController.'

【问题讨论】:

  • 它将帮助您展示您的故事板

标签: swift swift3


【解决方案1】:

您需要将源视图控制器嵌入到导航控制器中,或者将 segue 类型从 push 更改为其他内容。此外,尝试将您的目标控制器转换为 UINavigationController 以防止在初始错误之后出现不同的错误(如果已修复):

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if let navVC = segue.destinationViewController as? UINavigationController{
            if let historyVC = navVC.viewControllers[0] as? HistoryController{
                historyVC.detailItem = barcodeInt as AnyObject
            }
        }
    }

看看这是否适合你。

编辑:更新了上面的代码。

【讨论】:

  • 我将代码更改为您的代码,但出现此错误Value of type 'UINavigationController' has no member 'detailItem'
  • 使用 let controller = viewController.topViewController controller.detailItem =barcodeInt as AnyObject
【解决方案2】:

您的问题不在您的代码中,这很好,它在您的故事板中。

如果你想从 ViewController 推送到 HistoryVC,ViewController 应该嵌入在 UINavigationController 中,而不是 HistoryVC(它会通过它与 ViewController 的关系隐式嵌入)。

原因是被推送的 VC 必须嵌入在 UINavigationController 中,被推送的 vc 本质上是嵌入的,因为它被添加到 UINavigationController 的堆栈中。

如果初始 ViewController 不在 UINavigationController 中,则没有堆栈供推送的 ViewController (HistoryVC) 被推送到。基本上,您将堆栈的起点(您的第一个 ViewController)嵌入到 UINavigationController 中。

如果你想在几个 VC 之后开始一个新的堆栈,你可以将下一个视图控制器嵌入到一个新的 UINavigationController 中,但是你需要以模态方式进行。

【讨论】:

  • 你是如何生成这张图片的?
【解决方案3】:

试试这个:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if let navVC = segue.destinationViewController as? UINavigationController{
        if let historyVC = navVC.childViewControllers[0] as? HistoryController{
            historyVC.detailItem = barcodeInt as AnyObject
        }
    }
}

【讨论】:

    【解决方案4】:

    您应该使用show segue 而不是push segue。

    show segue 将尽可能将下一个 viewController 推送到第一个 viewcontroller 的 navigationController 堆栈中,否则它将使用modalPresent 显示下一个 viewController。

    如果你将你的第一个 viewController 嵌入到 UINavigationController 中,并且仍然保留你的 Navigation Controller,那么你使用push segue,你会得到一个异常:

    *** 由于未捕获的异常“NSInvalidArgumentException”而终止应用程序,原因:“不支持推送导航控制器”

    简单地将您的 segue 从 push 更改为 show 应该适合您的情况。

    【讨论】:

      【解决方案5】:
      override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
          if let nav = segue.destination as? UINavigationController {
              if let vc = nav.visibleViewController as? HistoryController {
                  vc.detailItem = barcodeInt as AnyObject
              }
          }
      }
      

      【讨论】:

        【解决方案6】:

        正如错误所说“如果你的源(第一个 viewController)没有嵌入到 navigationController 中,你就不能使用 push segue。

        您需要将 segue 的类型从“push”更改为“presentModally” - 通常应该可以。 您仍然可以继续使用 navigationController,但不能使用 push - push 只能在 NavigationController 内部使用。

        【讨论】:

          【解决方案7】:

          在我的故事板中,我有一个视图控制器,还有一个导航控制器和另一个名为 HistoryController 的视图控制器。 Navigation Controller 和 HistroyController 有关系“根视图控制器”

          我的第一个视图控制器上有一个按钮,并且该按钮有一个推送到导航控制器的按钮。

          现在这是您的问题。在故事板中,UINavigationController 和 FirstViewController 和 not 到 HistoryController 之间应该有 rootViewController 关系。然后,FirstViewController 中的按钮应该与HistoryController 有一个推送连接。见下图:

          另外,应用入口点应该是UINavigationController(只需拖动左侧的小箭头或选择UINavigationController,然后在右侧面板中检查Is initial controller)。

          【讨论】:

            【解决方案8】:

            问题是您尝试使用UIViewController 而不是UINavigationController 推送segue。

            按以下方式设置您的故事板:

            如您所见,第一个视图控制器正在向第二个视图控制器显示 segue,即包装在导航控制器中的内容。

            这样,当您触发 segue 时,只需使用以下代码访问您的 UIViewController 子类:

             override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
                    if let historyVC = segue.destination as? HistoryController {
                  // do what you need to.
                    }
             }
            

            如果您不需要专门针对HistoryController 的UINavigationController,则可以删除HistoryController 上面的那个,然后使用附加到第一个视图控制器的那个。

            【讨论】:

              【解决方案9】:

              要使用push segue ViewController 需要嵌入到 NavigationController 中。如果您不希望 ViewController 成为 NavigationController 的视图控制器堆栈的一部分,您可以使用以下命令在 HistoryController 中删除:

              override func awakeFromNib() {
                  navigationController?.setViewControllers([self], animated: false)
              }
              

              另一种方法是从 ViewController 到 NavigationController 的转场不是推送转场,例如如果您想控制 NavigationController 在屏幕中的显示方式,则以模态或自定义方式呈现。

              【讨论】:

                【解决方案10】:

                您是否也尝试过检查标识符?

                override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
                  if let nav = segue.destination as? UINavigationController where segue.identifier == "yourSegueIdentifierSetInTheStoryboard"{
                    if let vc = nav.visibleViewController as? HistoryController {
                        vc.detailItem = barcodeInt as AnyObject
                    }
                  }
                }
                

                【讨论】:

                  猜你喜欢
                  • 2017-03-03
                  • 1970-01-01
                  • 2015-08-21
                  • 1970-01-01
                  • 1970-01-01
                  • 2017-12-03
                  • 1970-01-01
                  • 1970-01-01
                  • 2015-04-24
                  相关资源
                  最近更新 更多