如何在导航控制器中关闭视图控制器,而不关闭整个堆栈

Posted

技术标签:

【中文标题】如何在导航控制器中关闭视图控制器,而不关闭整个堆栈【英文标题】:How to dismiss a view controller in a navigation controller, without dismissing the whole stack 【发布时间】:2017-03-19 16:54:20 【问题描述】:

基本上我有两个选项卡的选项卡栏控制器,每个选项卡都有一个单独的导航控制器,每个都有几个视图(见下文)。

在“顶部”导航控制器(在右侧标签中),我可以选择一个图像,然后被带到最右边的屏幕预览图像...

func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) 
    if let image = info[UIImagePickerControllerEditedImage] as? UIImage 

        let previewController = self.storyboard?.instantiateViewController(withIdentifier: "previewVC") as! PreviewViewController
        previewController.img = image
        previewController.navigationItem.setHidesBackButton(true, animated: false)
        self.navigationController?.pushViewController(previewController, animated: true)

        self.dismiss(animated: true, completion: nil)
    

...我点击“发布”的地方。这会上传图片并调用self.tabBarController?.selectedIndex = 0

这只是将我带到图像提要,它位于“底部”导航控制器(左侧选项卡)中。到现在为止还挺好。但是,当我需要在发布后显示上传屏幕时,预览屏幕仍然显示在“右侧”选项卡中。

如果我在点击 post 时调用 self.dismiss(animated: true, completion: nil),整个导航控制器将被关闭,我将返回登录屏幕。

所以我试图关闭预览控制器,以便上传控制器显示为右侧选项卡中的默认视图,而不关闭导航控制器中的整个堆栈。

我该怎么做?

【问题讨论】:

不完全遵循您的导航结构,但我提供了一些可能解决您的问题的答案。让我知道我是否在正确的轨道上。 【参考方案1】:

如果您使用navigation controllers 将视图控制器添加到导航堆栈(推送),您可以通过调用弹出函数将其移除。当你以模态方式呈现视图控制器时,你调用了dismiss来移除视图控制器。

【讨论】:

问题是,如果我在上传函数中调用self.navigationController?.popViewController(animated: true),它确实会将上传控制器带回屏幕,但是上传控制器有一个viewWillAppear,它会检查设备是否有相机与否,如果没有,它会直接进入图像选择器。 所以在这种情况下,当预览控制器从视图中弹出时,选择器就会重新呈现。我需要返回另一个选项卡中的提要,而无需再次显示上传控制器 - 尽管同时我需要上传控制器作为第二个选项卡中的默认视图。 Don't present the image picker in view 将出现。也许将它移动到查看确实加载所以它只被调用一次。 所以我最终将 pop 放在了上传功能中 self.tabBarController?.selectedIndex = 0 之前。这有点乱,但它有效 - 我在发布后被带回提要,然后如果我返回右侧选项卡,我会看到预览控制器滑开并显示正确的(上传)控制器。感谢您提供有关在viewDidLoad 中进行相机检查的提示。这解决了选择器在尝试返回提要时挡住路的直接问题,但我确实希望在没有摄像头的情况下每次显示该屏幕时选择器都呈现自己。 只是在我试图关闭预览控制器并返回提要时。【参考方案2】:

委托函数为您提供(图像选择器)视图控制器,您应该关闭它,而不是作为委托的视图控制器(通常是呈现视图控制器)。也许尝试这样的事情:

func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) 
    if let image = info[UIImagePickerControllerEditedImage] as? UIImage 

        let previewController = self.storyboard?.instantiateViewController(withIdentifier: "previewVC") as! PreviewViewController
        previewController.img = image
        previewController.navigationItem.setHidesBackButton(true, animated: false)
        self.navigationController?.pushViewController(previewController, animated: true)

        picker.dismiss(animated: true, completion: nil)
    

【讨论】:

以上是关于如何在导航控制器中关闭视图控制器,而不关闭整个堆栈的主要内容,如果未能解决你的问题,请参考以下文章

在 UITabController 中关闭视图控制器

如何从堆栈中弹出视图控制器而不导航到它们

如何在 appdelegate 中关闭视图控制器?

无法在 Interface Builder 中关闭键盘,因为视图控制器不会显示 doneEditing:

导航控制器如何弹出整个堆栈,包括根

如何检查视图控制器是不是已在 Swift 中关闭