Table view not updating when called from another View Controller using NotificationCenter

Viewed 217

I have a table view in one view controller. I want to update the table view from another VC. I'm doing this using NotificationCenter like this:

In the table view VC:

override func viewDidLoad() {
    super.viewDidLoad()

    NotificationCenter.default.addObserver(self, selector: #selector(self.updateTableView), name: NSNotification.Name(rawValue: "updateTableView"), object: nil)
}

@objc func updateTableView() {
    print("in func")
    DispatchQueue.main.async {
        self.listTV.reloadData()
    }
}

In the opened VC:

func reloadTV() {
       NotificationCenter.default.post(name: NSNotification.Name(rawValue: "updateTableView"), object: nil)
}

The print works, but the table view doesn't reload. I can only see it changing if I dismiss the VC with the table view and open it again.

I've followed the suggestions of other answers which is to use DispatchQueue, but that didn't make a difference. What am I missing?

Many thanks!

3 Answers

I would consider doing this by protocol and delegate instead of notifications... This is how I do it.

When you call tableView.reloadData(). It has no effect if the tableView is hidden (isHidden == true). I believe the behavior is also the same when the tableView is effectively hidden by another ViewController (so effectively hidden).

Solution: A suggestion is to reload the tableView when the view is shown again. Few ways to do that. one is in viewDidAppear (depends on how you transitioned between ViewControllers), or

you can keep a reference to the tableView and after you dismiss the second ViewController (in which you were sending the notification) you provide the callback to reload the tableView. Roughly like the snippet, with self being the secondViewController you transitioned to. Dismiss that view

  self.dismiss(animated: true, completion: {
            self.tableView.reloadData()
        }

or you can still use your notification and setup a flag and when the viewDidAppear, you then reloadData() inside viewDidAppear. However for this to work, you need to ensure that viewDidAppear is always called when the view is shown again (this will depend on how you transitioned between views).Simply override that method and print to verify.

There are other ways but the bottom line is tableView.reloadData() will be ignored if it is called when the tableView is not visible on the screen. My guess is it's an optimization made by Apple (no need to reload if no table is showing) or maybe a bug. I think they'll say it's a feature

I suggest instead of using NotificationCenter, to instead set a Bool, tableViewNeedsUpdate, and check for the value of that Bool when the view with the UITableView is presented, and the UITableView is visible and able to accept reloadData() calls. After the reload is complete, set the variable back to false.

Related