Swift: Reload data in UITableView element triggered in an external class

195 Views Asked by At

I'm trying to call the reloadData() method to update a table view in an external class (different view controller), using the method viewDidDisappear().

I can already update the table view when the view where it is located is loaded or appears:

class OrderHistoryController: UIViewController, UITableViewDataSource, UITableViewDelegate {
    
    @IBOutlet var orderTable: UITableView!
    
    //called when order table is loaded or appears
    override func viewDidLoad() {
        super.viewDidLoad()
        self.orderTable.delegate = self
        self.orderTable.dataSource = self
        self.orderTable.reloadData()
    }
    override func viewDidAppear(_ animated: Bool) {
        self.orderTable.delegate = self
        self.orderTable.dataSource = self
        self.orderTable.reloadData()
    }
    // ...
}

But I want the table to be reloaded when another view disappears.

class OrderDocumentationController: UIViewController {
      
    override func viewDidDisappear(_ animated: Bool) {
        OrderHistoryController().orderTable.reloadData()
        return
    }
    // ...
}

I get the fatal error:

Unexpectedly found nil while implicitly unwrapping an Optional value.

Guess it is just a rookie mistake. Any ideas? Thank you in advance!

2

There are 2 best solutions below

2
On

No need to reload orderTable if OrderHistoryController appears when OrderDocumentationController disappears. Since, self.orderTable.reloadData() is called in OrderHistoryController::viewDidAppear()

UPDATE:

A better approach would be to have OrderDocumentationController provide a block which is called when the modal controller has completed.

So in OrderDocumentationController, provide a block property say with the name onDoneBlock.

In OrderHistoryController you present as follows:

  • In OrderHistoryController, create OrderDocumentationController

  • Set the done handler for OrderDocumentationController as: OrderDocumentationController.onDoneBlock={[OrderDocumentationController dismissViewControllerAnimated:YES completion:nil]};

  • Present the OrderDocumentationController controller as normal using [self OrderDocumentationController animated:YES completion:nil];

  • In OrderDocumentationController, in the cancel target action call self.onDoneBlock();

The result is OrderDocumentationController tells whoever raises it that it is done. You can extend the onDoneBlock to have arguments which indicate if the modal completed, cancelled, succeeded etc.

1
On

When you call OrderHistoryController().orderTable.reloadData(), this will create a new OrderHistoryController instance, that will have not orderTable outlet connected hence resulting in the crash.

There are differnt ways to achieve what you want:

  • Store a reference to the OrderHistoryController instance and use this
  • Maybe better: Implement some custom delegation mechanism
  • Use the NotificationCenter to send a message that then will result in a refresh