关闭一个视图控制器并显示另一个视图控制器

Posted

技术标签:

【中文标题】关闭一个视图控制器并显示另一个视图控制器【英文标题】:Dismissing a View Controller and displaying another View Controller 【发布时间】:2016-10-03 02:45:44 【问题描述】: 我有三个 ViewController - V1 V2 和 V3。 按钮点击V1,ViewController V2显示动画 水平翻转。

现在在 V2 中单击按钮时,应关闭 ViewController 返回 V1 并显示 ViewController V3。

我尝试了这段代码来实现这个功能。但它不起作用。请帮忙!

注意 : V2 和 V3 在同一个 StoryBoard(开始)中。 V1 在不同的故事板(主)中。

var VC3 : ViewController3?

        let mainStoryboard: UIStoryboard = UIStoryboard(name: "start",bundle: nil)

 self.dismissViewControllerAnimated(false, completion: 
            self.VC3 = (mainStoryboard.instantiateViewControllerWithIdentifier("ViewController3") as! ViewController3)
            self.presentViewController(self.VC3!, animated: true, completion: nil)
        )

更新- 我收到此警告 尝试在其视图不在窗口层次结构中的 ViewController2 上呈现 ViewController3!

【问题讨论】:

你有没有研究过 unwind segues?如果你已经去了 v1 -> v2 -> v3,然后想直接回到 v1,那么放松 segues 是要走的路。 @Michael 这实际上是我的路径 - v1->v2->(dismiss)v1->v3 好的,现在我明白了。我仍然会使用 v2 -> v1 的 unwind segue。在 v1 中执行 unwind,目前 v3。我会给你更多的细节作为答案,但我目前没有 XCode。 @Michael,你认为这不可能通过dismissViewControllerAnimated 实现吗?我不能在这里使用 segue :(。它有点复杂.. V2 包含 5 个子视图。点击 V2 的按钮实际上来自其中一个子视图。 @iNishinKareem 等 5 分钟,我会给你一个示例项目来测试.. 【参考方案1】:

我复制了您的查询并创建了 3 个视图控制器:VC1、VC2 和 VC3。 我使用 Delegates 和 Segues 实现了这一点。 Storyboard Setup。

VC1.Swift:

class VC1: UIViewController, VC2Delegate 

    override func viewDidLoad() 
        super.viewDidLoad()

        // Do any additional setup after loading the view.
    

    func showVC3() 
        self.performSegueWithIdentifier("VC1ToVC3", sender: nil)
    

    // MARK: - Navigation
    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) 
        if segue.identifier == "VC1ToVC2" 
            if let destVC = segue.destinationViewController as? VC2 
                destVC.delegate = self
            
        
    


VC2.Swift:

protocol VC2Delegate 
    func showVC3()


class VC2: UIViewController 
    var delegate:VC2Delegate?

    override func viewDidLoad() 
        super.viewDidLoad()

        // Do any additional setup after loading the view.
    

    @IBAction func actBack()
        self.dismissViewControllerAnimated(true, completion: nil)
        if let _ = delegate 
            delegate?.showVC3()
        
    


【讨论】:

我觉得这个很简单;)【参考方案2】:

警告指出“您在 ViewController2 上呈现 ViewController3,但 ViewController2 不在视图层次结构中!”。这意味着 ViewController2 在 ViewController3 出现之前已经关闭。所以不可能在 ViewController2 上呈现 ViewController 3

使用此示例代码:

ViewController1

import UIKit

class ViewController: UIViewController, presentViewControllerThree

    @IBAction func displayViewControllerTwoOnClick(_ sender: AnyObject) 
        let currentStoryboard: UIStoryboard = UIStoryboard(name: "Start",bundle: nil)
        let  vc2: ViewController2 = currentStoryboard.instantiateViewController(withIdentifier: "viewcont2") as! ViewController2
        vc2.delegate = self
        self.navigationController?.present(vc2, animated: true, completion: nil)
    

    func presentVC3()
        let currentStoryboard: UIStoryboard = UIStoryboard(name: "Start",bundle: nil)
        let  vc3: ViewController3 = currentStoryboard.instantiateViewController(withIdentifier: "viewcont3") as! ViewController3

         self.navigationController?.present(vc3, animated: true, completion: nil)
    


ViewController2

 import UIKit

protocol presentViewControllerThree 
    func presentVC3()


class ViewController2: UIViewController 

    var delegate: presentViewControllerThree?

    @IBAction func dismissViewControllerOnClick(_ sender: AnyObject) 

        self.dismiss(animated: true, completion: nil)
        delegate?.presentVC3()

    


ViewController3

   import UIKit

class ViewController3: UIViewController 

    @IBAction func dismissViewControllerOnClick(_ sender: AnyObject) 

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



Main.storyboard 截图:

Start.storyboard:

请查看我的 GitHub 链接以测试示例项目:

https://github.com/k-sathireddy/DismissPresentViewControllers

【讨论】:

【参考方案3】:

错误信息非常具有描述性:

尝试在 ViewController2 上显示 ViewController3 不在窗口层次结构中!

让我们看看你现有的代码:

 self.dismissViewControllerAnimated(false, completion: 
            self.VC3 = (mainStoryboard.instantiateViewControllerWithIdentifier("ViewController3") as! ViewController3)

            //Using self here is causing that error
            self.presentViewController(self.VC3!, animated: true, completion: nil)
)

在完成处理程序中,您尝试从self 呈现VC3...但self 指的是您刚刚解雇的ViewController。这就是该错误消息告诉您的内容。

相反,您需要从 VC2 的父级出示 VC3。您可以通过presentingViewController 属性来实现这一目标:

 self.dismissViewControllerAnimated(false, completion: 
            self.VC3 = (mainStoryboard.instantiateViewControllerWithIdentifier("ViewController3") as! ViewController3)
            self.presentingViewController.presentViewController(self.VC3!, animated: true, completion: nil)
)

【讨论】:

我猜是self.VC3! presentViewController 的值为 null 可能。虽然我怀疑这里实际发生的情况是 ViewController2 永远不会被垃圾收集,因为它保持对 VC3 的强引用。无论哪种方式,上面的答案都更加完整

以上是关于关闭一个视图控制器并显示另一个视图控制器的主要内容,如果未能解决你的问题,请参考以下文章

使用一个视图控制器从用户那里获取文本,将该值添加到数据库并在另一个 VC 中显示它[关闭]

如何关闭自己的视图控制器并在按钮点击中呈现另一个视图控制器?

在关闭另一个模式视图控制器后呈现一个模式视图控制器

iOS 8 – 在设置关键窗口或关闭并立即呈现另一个视图控制器后快速呈现视图控制器时出现故障

将模态呈现的视图控制器关闭到不同的底层视图控制器

将数据从带有页面控制器的 uiscrollview 传递到另一个视图控制器 [关闭]