Swift 3 - 将segue推送到导航控制器

时间:2016-10-19 17:59:47

标签: swift swift3

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

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

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

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.'

10 个答案:

答案 0 :(得分:9)

您需要将源视图控制器嵌入到导航控制器中,或将segue类型从推送更改为其他内容。此外,尝试将目标控制器转换为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
            }
        }
    }

看看它是否适合你。

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

答案 1 :(得分:1)

你的问题不在你的代码中,没关系,它在你的故事板中。

如果您想从ViewController推送到HistoryVC,ViewController应嵌入UINavigationController,而不是HistoryVC(它将与ViewController的关系隐式嵌入)。

这样做的原因是推送的VC必须嵌入到UINavigationController中,正在推送的vc本身是嵌入式的,因为它被添加到UINavigationController的堆栈中。

enter image description here

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

如果你想在新的堆栈中启动一个新的堆栈,你可以在新的UINavigationController中嵌入下一个视图控制器,但是你需要以模态方式进行转换。

答案 2 :(得分:1)

试试这个:

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

答案 3 :(得分:1)

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

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

如果你将第一个viewController嵌入到UINavigationController中,并且仍然保留你的导航控制器,那么你使用push segue,你会得到一个例外:

  

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

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

答案 4 :(得分:0)

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

答案 5 :(得分:0)

如错误所示“如果您的源(第一个viewController)没有嵌入navigationController中,则无法使用push segue。

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

答案 6 :(得分:0)

  

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

     

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

现在这是你的问题。在您的故事板中,您应该rootViewControllerUINavigationController之间以及FirstViewController之间存在HistoryController关系。然后,FirstViewController中的按钮应与HistoryController建立推送连接。见下图:

enter image description here

此外,应用入口点应为UINavigationController(只需拖动左侧小箭头或选择UINavigationController,然后选择右侧底板检查Is initial controller)。

enter image description here

答案 7 :(得分:0)

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

按以下方式设置故事板: enter image description here

正如您所看到的,第一个视图控制器正在向第二个视图控制器显示segue,它包含在导航控制器中。

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

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

如果您不需要专门针对UINavigationController单独HistoryController,则可以删除HistoryController以上的<path id="#ondasAceite" ... ,并使用附加到第一个视图控制器的那个。

答案 8 :(得分:0)

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

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

另一种方法是从ViewController到NavigationController的segue不是push segue,例如如果要控制NavigationController在屏幕中显示的方式,请显示模态或自定义。

答案 9 :(得分:0)

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

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