Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UITableView's reloadRowsAtIndexPaths: (NSArray *) indexPaths failing to cause a reload unless you call it twice?

I have a UITableViewController managing a UITableView object in an iPad app. The table view is tied in with a rather complicated constellation of other objects. I am having a problem when I ask it to reload a row as follows:

//indexPath is an NSIndexPath with indexes 0 and 0.  At the moment, this is the only cell in the table view.
NSArray *array = [NSArray arrayWithObject:indexPath]; 
[self.tableView reloadRowsAtIndexPaths:array withRowAnimation:UITableViewRowAnimationNone]; 

The problem is that the row does not reload. There is never a callback to cellForRowAtIndexPath.

The crazy thing is that if I call reloadRowsAtIndexPaths twice, the second call does trigger the reload:

//indexPath is an NSIndexPath with indexes 0 and 0.  At the moment, this is the only cell in the table view.
NSArray *array = [NSArray arrayWithObject:indexPath]; 
[self.tableView reloadRowsAtIndexPaths:array withRowAnimation:UITableViewRowAnimationNone];   // does not reload
[self.tableView reloadRowsAtIndexPaths:array withRowAnimation:UITableViewRowAnimationNone];   // does reload

I am wondering if anyone else has ever encountered a bug like this, and if so, what was the cause?

like image 795
William Jockusch Avatar asked Apr 05 '11 19:04

William Jockusch


2 Answers

reloadRowsAtIndexPaths:... only works when wrapped inbetween calls to:

- (void)beginUpdates;
- (void)endUpdates;

Outside of that, behavior is undefined. (and as you've discovered, fairly unreliable).

Edit: quoting relevant part of "Table View Programming Guide for iPhone OS":

To animate a batch insertion and deletion of rows and sections, call the insertion and deletion methods within an animation block defined by successive calls to beginUpdates and endUpdates. If you don’t call the insertion and deletion methods within this block, row and section indexes may be invalid. beginUpdates...endUpdates blocks are not nestable.

At the conclusion of a block—that is, after endUpdates returns—the table view queries its data source and delegate as usual for row and section data. Thus the collection objects backing the table view should be updated to reflect the new or removed rows or sections.

The reloadSections:withRowAnimation: and reloadRowsAtIndexPaths:withRowAnimation: methods, which were introduced in iPhone OS 3.0, are related to the methods discussed above. They allow you to request the table view to reload the data for specific sections and rows instead of loading the entire visible table view by calling reloadData.

like image 52
amattn Avatar answered Oct 22 '22 10:10

amattn


I know this topic is kind of old, but I came across the same issue and a simple fix. I had a table view and when I called reloadData and/or reloadRowsAtIndexPaths, the tableview method cellForRowAtIndexPath would not fire.

It turns out I hadn't hooked up my tableview IBOutlet in Interface Builder - once that was hooked up everything fired as expected. It's always the little things...

Also, like others have mentioned, if you only need the one call, wrapping it in begin/endUpdates isn't necessary.

like image 40
R_B Avatar answered Oct 22 '22 08:10

R_B