14

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

A_toaster
  • 811
  • 2
  • 16
  • 47

3 Answers3

5

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.

caesic
  • 81
  • 1
  • 2
4

You can simply reaload your data in viewDidAppear:, but that might cause the table to be refreshed unnecessarily in some cases.

A more flexible solution is to use protocols as you have correctly guessed.

Let's say the class name of your first tableViewController is Table1VC and the second one is Table2VC. You should define a protocol called Table2Delegate that will contain a single method such as table2WillDismissed.

protocol Table2Delegate {
    func table2WillDismissed()
}

Then you should make your Table1VC instance conform to this protocol and reload your table within your implementation of the delegate method.

Of course in order for this to work, you should add a property to Table2VC that will hold the delegate:

weak var del: Table2Delegate?

and set its value to your Table1VC instance.

After you have set your delegate, just add a call to the delegate method right before calling the dismissViewControllerAnimated in your Table2VC instance.

del?.table2WillDismissed()
self.dismissViewControllerAnimated(true, completion: {})

This will give you precise control over when the table will get reloaded.

Cihan Tek
  • 4,771
  • 3
  • 19
  • 28
  • 1
    The behaviour of the OS is the same regardless of the language you use. – Cihan Tek Apr 10 '15 at 15:06
  • It looks nicer if you do it in the viewWillAppear; as the table appears loaded already. if you do it in the viewDidAppear; you'll get the table and after a fraction of time it will get loaded. And yes swift also calls viewWillAppear/viewDidAppear after dismissing the view controller – Loebre Nov 15 '15 at 11:31
  • 1
    override func viewDidAppear(_ animated: Bool) { // code I want to execute } Worked perfectly for me – DMH Apr 21 '17 at 16:55
4

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)