Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can you reload a ViewController after dismissing a modally presented view controller in Swift?

I have a first tableViewController which opens up a second tableViewcontroller upon clicking a cell. The second view controller is presented modally (Show Detail segue) and is dismissed with:

self.dismissViewControllerAnimated(true, completion: {})

At this point, the second view controller slides away and reveals the first view controller underneath it. I would then like to reload the first view controller. I understand that this may require use of delegate functions, but not sure exactly how to implement it

like image 424
A_toaster Avatar asked Feb 24 '15 21:02

A_toaster


People also ask

How do I refresh ViewController after dismiss method is called?

So, viewWillAppear in ViewControllerA will not be called after dimissing ViewControllerB. If you don't want to change the modalPresentationStyle to fullScreen then you can use closures for passing data to ViewControllerA when you're dismissing ViewControllerB.

How do I refresh a ViewController?

When you want to reload, call loadData() again to get the data from model. In a tableView call reloadData() or in a regular view setNeedsDisplay(). Save this answer.

How do I dismiss a presented ViewController?

When it comes time to dismiss a presented view controller, the preferred approach is to let the presenting view controller dismiss it. In other words, whenever possible, the same view controller that presented the view controller should also take responsibility for dismissing it.


2 Answers

Swift 5:

You can access the presenting ViewController (presentingViewController) property and use it to reload the table view when the view will disappear.

class: FirstViewController {
    var tableView: UITableView

    present(SecondViewController(), animated: true, completion: nil)
}

In your second view controller, you can in the viewWillDisappear method, add the following code:

class SecondViewController {
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)

        if let firstVC = presentingViewController as? FirstViewController {
            DispatchQueue.main.async {
                firstVC.tableView.reloadData()
            }
        }
    }
}

When you dismiss the SecondViewController, the tableview of the FirstViewController will reload.

like image 99
caesic Avatar answered Sep 27 '22 22:09

caesic


I solved it a bit differently since I don't want that dependancy.

And this approach is intended when you present a controller modally, since the presenting controller wont reload when you dismiss the presented.

Anyway solution!

Instead you make a Singleton (mediator)

protocol ModalTransitionListener {
    func popoverDismissed()
}

class ModalTransitionMediator {
    /* Singleton */
    class var instance: ModalTransitionMediator {
        struct Static {
            static let instance: ModalTransitionMediator = ModalTransitionMediator()
        }
        return Static.instance
    }

private var listener: ModalTransitionListener?

private init() {

}

func setListener(listener: ModalTransitionListener) {
    self.listener = listener
}

func sendPopoverDismissed(modelChanged: Bool) {
    listener?.popoverDismissed()
}
}

Have you Presenting controller implement the protocol like this:

class PresentingController: ModalTransitionListener {
//other code
func viewDidLoad() {
    ModalTransitionMediator.instance.setListener(self)
}
//required delegate func
func popoverDismissed() {
    self.navigationController?.dismissViewControllerAnimated(true, completion: nil)
    yourTableViev.reloadData() (if you use tableview)
}
}

and finally in your PresentedViewController in your viewDid/WillDisappear func or custom func add:

ModalTransitionMediator.instance.sendPopoverDismissed(true)
like image 31
Mikael Stenberg Avatar answered Sep 27 '22 22:09

Mikael Stenberg