Reload UITableView when navigating back?

IphoneObjective CNavigation

Iphone Problem Overview


I have a top level UIViewController that contains a UITableView. The top level UIViewController instantiates a NavigationController, and pushes another UIViewController onto the NavigationController. I.E. we push into a new, second view. This second view has the usual "Back" button in the upper left hand corner to allow you to navigate back to the top level view.

Is it possible, when navigating back to the top level view from the second view, to redraw the UITableView in the top level view, using data generated in the second view, by calling cellForRowAtIndexPath in the top level and if so, how does one do this?

Iphone Solutions


Solution 1 - Iphone

All you need to do is this (in your UIViewController that has a UITableView). You don't have to worry about what happens at cell-level at this point.

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    [self.tableView reloadData]; // to reload selected cell
}

Just add the code above to your controller, and you'll see that the right thing happens when you come back from your second view. The call to reloadData tells the table view that it needs to refresh its cells from your model, and everything else follows nicely.

Solution 2 - Iphone

If you only want to reload the cell that was selected, override viewWillAppear: in your custom subclass of UITableViewController like so:

- (void)viewWillAppear:(BOOL)animated
{
    NSIndexPath *selectedRowIndexPath = [self.tableView indexPathForSelectedRow];
    [super viewWillAppear:animated]; // clears selection
    if (selectedRowIndexPath) {
        [self.tableView reloadRowsAtIndexPaths:@[selectedRowIndexPath] withRowAnimation:UITableViewRowAnimationNone];
    }
}

NOTE: Assuming you've left clearsSelectionOnViewWillAppear set to YES (the default), you must get the index path of the selected row before calling super, which clears the selection.

Also, the solution of @ZoranSimic to just call [self.tablView reloadData] is acceptable as it's less code and still efficient.

Finally, perhaps the best way to keep your table view's cells in sync with the model objects they represent is to do like NSFetchedResultsController and use key-value observing (KVO) and/or NSNotification to inform your table view controller when model objects have changed so that it can reload the corresponding cells. The table view controller could begin observing changes to its model objects in viewDidLoad and end observing in dealloc (and anywhere you manually unload self.view).

Solution 3 - Iphone

In addition to the answer of Zoran Simic here the Swift code:

override func viewWillAppear(animated: Bool) {
    super.viewWillAppear(animated)
    tableView.reloadData()
}

Solution 4 - Iphone

You could implement the methods of UINavigationControllerDelegate and create the logic for the refreshing when popping view controllers.

Another way to do this would be implementing on your table view controller some logic on viewWillAppear, to refresh based on the data of the popped view controller.

If you need to send data from the second view controller to the first view controller, remember that your second view controller "doesn't" know the existence of the previous view controller. It should be transparent for it. You should implement some protocol to make the second view controller send data to the first view controller. It would be a third option to this problem, since your first view controller would be the delegate and the second view controller would be sending info to the delegate, you could be preparing your table view (first view controller) to reload, based on the received data.

Solution 5 - Iphone

viewWillAppear gets called every time the view appears include the first time. Here is my solution for reload the view only when you navigate back

I create one variable in .h file of my ViewController for checking that it is the first time I go to this ViewController or when I navigate back

@property (nonatomic) BOOL isViewExist;

After that in viewWillAppear

-(void)viewWillAppear:(BOOL)animated{
    if(!self.isViewExist){
        self.isViewExist = YES; // check it is the first time you go to this ViewController -> don't reload anything
    }else{
        [self.tableView reloadData]; // to reload the tableview data
        // or your can refresh anything in your ViewController as you want
    }
}

Hope this help

Solution 6 - Iphone

Maybe can help now.

For Swift 2+

In your viewDidAppear method:

If you want to reload all table:

tableView.reloadData()

If you want to reload only the cell selected.

let index = tableView.indexPathForSelectedRow
if (index != nil){
  self.tableView.reloadRowsAtIndexPaths([index], withRowAnimation: UITableViewRowAnimation.Automatic)
}

Solution 7 - Iphone

Updated for Swift 3

let index = tableView.indexPathForSelectedRow
    if (index != nil){
        self.tableView.reloadRows(at: [index!], with: UITableViewRowAnimation.automatic)
    }

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJames TestaView Question on Stackoverflow
Solution 1 - IphoneZoran SimicView Answer on Stackoverflow
Solution 2 - Iphonema11hew28View Answer on Stackoverflow
Solution 3 - IphoneMichael DornerView Answer on Stackoverflow
Solution 4 - IphonevfnView Answer on Stackoverflow
Solution 5 - IphoneLinhView Answer on Stackoverflow
Solution 6 - IphoneDasogaView Answer on Stackoverflow
Solution 7 - IphoneRobin ThomsonView Answer on Stackoverflow