如何关闭当前的 ViewController 并在 Swift 中更改为新的 ViewController?

Posted

技术标签:

【中文标题】如何关闭当前的 ViewController 并在 Swift 中更改为新的 ViewController?【英文标题】:How to dismiss the current ViewController and change to the new ViewController in Swift? 【发布时间】:2018-03-05 09:32:08 【问题描述】:

我是 ios swift 的新手。我有三个 ViewController。 page-A 是根控制器,它将呈现给 page-B。它在页面 B 中有一个计时器。 5秒后,View会从page-B切换到page-C,同时关闭page-B。

ViewControll-B

class AViewController: UIViewController 

    var timer: Timer?

    override func viewDidLoad() 
        super.viewDidLoad()

        //set the timer , and chagne view to C ViewController
        Timer.scheduledTimer(timeInterval: 5,
                             target: self,
                             selector: #selector(self.changeToAnswerView),
                             userInfo: nil,
                             repeats: false)
    


    @objc func changeToAnswerView() 
        dismissLoader()
    

    func dismissLoader() 
        dismiss(animated: true) 
            print("Dismissing Loader view Controller")
        
    

    override func viewWillDisappear(_ animated: Bool) 
        //change view to Answer ViewController
        let filterVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "CViewControllerID")
        filterVC.modalPresentationStyle = UIModalPresentationStyle.custom
        self.present(filterVC, animated: true, completion: nil)
    


定时器执行 5 秒后,BViewController 将自行关闭并呈现给BViewController

但是会出现以下错误:

whose view is not in the window hierarchy

我错过了什么吗?

问题: 如何在 Swift 中关闭当前的 ViewController 并更改为新的 ViewController?

提前致谢。

【问题讨论】:

您之前是否从任何其他控制器展示控制器 A?或控制器是在应用加载时首次显示的根控制器 为什么要关闭当前的 ViewController? @iOSGeek 我的错。它有三个视图控制器,我有编辑。 为此使用协议, 检查工作输出我发布了一个答案 【参考方案1】:

这是你可以尝试的工作代码

您的控制器已被解雇并倾向于制作一个新控制器

import UIKit

class pdfVC: UIViewController


    var timer : Timer?

    override func viewDidLoad()
    
        super.viewDidLoad()
        timer = Timer.scheduledTimer(timeInterval: 3, target: self, selector: #selector(pdfVC.timerAction), userInfo: nil, repeats: false)
    

    @objc func timerAction()
    
        if timer != nil 
            timer?.invalidate()
            dismiss(animated: true, completion: 
                print("Dismissed")
            )
        
    

    override func viewWillDisappear(_ animated: Bool) 
        if self.isBeingDismissed 
            let filterVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "demoViewController")
            filterVC.modalPresentationStyle = UIModalPresentationStyle.custom
            print("called")
            self.presentingViewController?.present(filterVC, animated: true, completion: nil)
        
    

输出

【讨论】:

【参考方案2】:

尝试将dismissLoader函数更改为:

func dismissLoader() 
    dismiss(animated: true) 
        print("Dismissing Loader view Controller")
        if let presentingController = self.presentingViewController 
            let filterVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "BViewControllerID")
            filterVC.modalPresentationStyle = UIModalPresentationStyle.custom
            presentingController.present(filterVC, animated: true, completion: nil)
        
    

并移除 viewWillDisappear 函数。

问题是您试图在被解除(即从窗口层次结构中删除)后从加载器中呈现 BViewController,而此时不存在。

因此,解决方案是您可以获得对正在呈现加载器的呈现视图控制器的引用,该控制器将在关闭加载器并从那里呈现新视图控制器后出现。

【讨论】:

我试过了,没有显示错误,也没有显示C-Viewcontroller。 如果 AViewController 是根视图控制器,那么看看这个答案:***.com/a/22654105/3882414 但是如果你有另一个视图控制器正在呈现 AViewController 那么上面的代码应该可以工作【参考方案3】:

在你的 B 视图控制器被解散后, 在其完成处理程序中

 self.dismiss(animated: true) 
     if let presentingVC = self.presentingViewController 
        present c view controller here
     
 

以上是一种方式,另一种方式是通过委托

在视图控制器中:

if let bVC = self.storyboard.instantiateViewController(withIdentifier: B.controllerIdentifier) as? B  

        bVC.delegate = self
        self.present(bVC, animated: true, completion: nil)
    

B 视图控制器内部

为协议添加委托方法

protocol BProtocol: class 
    func didClose()

在 B 中解散

 var delegate:  BProtocol?
self.dismiss(animated: true) 
     self.delegate?.didClose()
 

这个委托将由 A ViewController 实现为

extension AViewController: BProtocol 
    func didClose() 
        //present C
    

【讨论】:

【参考方案4】:

您正在尝试使用视图控制器的引用(实例),该引用将不再存在于内存中。

试试这个

if let presentingVC = self.presentingViewController 
        let filterVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "CViewControllerID")
        filterVC.modalPresentationStyle = UIModalPresentationStyle.custom
        presentingVC.present(filterVC, animated: true, completion: nil)

注意:一旦您当前的视图控制器被关闭,就会呈现一个新的视图控制器 (filterVC)。视图控制器一次只能呈现一个视图控制器(如果您选择以模态方式呈现)。延迟 1 秒后执行此操作..

编辑

试试这个编辑过的代码。

Class AViewController: UIViewController 

    var timer: Timer?
    var presentingVC: UIViewController?
    override func viewDidLoad() 
        super.viewDidLoad()

        //set the timer , and chagne view to C ViewController
        Timer.scheduledTimer(timeInterval: 5,
                             target: self,
                             selector: #selector(self.changeToAnswerView),
                             userInfo: nil,
                             repeats: false)
    


    @objc func changeToAnswerView() 
        dismissLoader()
    

    func dismissLoader() 
        dismiss(animated: true) 
            print("Dismissing Loader view Controller")
        
    

    override func viewDidAppear(_ animated: Bool) 
         super.viewDidAppear(animated)
        //change view to Answer ViewController
        if let presentingVC = self.presentingViewController 
           self.presentingVC = presentingVC
        
    

    override func viewWillDisappear(_ animated: Bool) 
        //change view to Answer ViewController
        super.viewWillDisappear(animated)
       if let presentingVC = self.presentingVC 

        let filterVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "CViewControllerID")
        filterVC.modalPresentationStyle = UIModalPresentationStyle.custom
        presentingVC?.present(filterVC, animated: true, completion: nil)

       else 
         print("Presenting View controller is nil")
      
    


【讨论】:

我试过了,没有显示错误,也没有显示C-Viewcontroller。 那是因为您当前的视图控制器仍然存在。一旦您关闭当前的视图控制器,就呈现它。一个视图控制器一次只能呈现一个视图控制器。延迟 1 秒后执行此操作。如果无法执行,请告诉我。我将与您分享完整的功能代码。 我延迟了1秒,但还是没有输入let presentingVC = self.presentingViewController

以上是关于如何关闭当前的 ViewController 并在 Swift 中更改为新的 ViewController?的主要内容,如果未能解决你的问题,请参考以下文章

如何将第二个viewcontroller文本字段值传递给第一个viewcontroller数组并在swift4中点击按钮时关闭

Swift:关闭在当前上下文中显示图片的 ViewController 时不时冻结屏幕

关闭一个 ViewController 并在 iOS 中启动另一个(不是重复的,其他答案不起作用)

错误 - (void)reloadData [关闭]

模态viewController关闭按钮问题

关闭呈现 viewController 不起作用并出现警告消息