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

21,297

Solution 1

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.

Solution 2

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.

Share:
21,297
William Jockusch
Author by

William Jockusch

Free Graphing Calculator -- iOS: https://itunes.apple.com/us/app/free-graphing-calculator/id378009553?mt=8 Android: https://play.google.com/store/apps/details?id=com.jockusch.freegraphingcalculator Mac: https://itunes.apple.com/us/app/free-graphing-calculator-2/ Windows: https://www.microsoft.com/store/apps/9pgllk5gj04h

Updated on February 27, 2020

Comments

  • William Jockusch
    William Jockusch over 4 years

    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?

    • Daniel
      Daniel about 13 years
      are you doing this in some background thread?
    • William Jockusch
      William Jockusch about 13 years
      Main thread. If by "test case", you mean a simple example that illustrates the same thing, no I don't have one, and I wish I did.
    • Madman
      Madman about 9 years
      Have the same issue, I'm using Xcode 6.3.2 and swift 1.2 and can't reload certain row from one call. Tried almost everything, but cell get refreshed only from second sequential reloadRowsAtIndexPaths call.
    • Rajesh
      Rajesh almost 9 years
      Got any answer to solve it?
  • amattn
    amattn about 13 years
    This problem killed me for a week last year... And it does say, but it's buried in the table view programming guide, not the reference doc.
  • amattn
    amattn about 13 years
    added the relevant part from apple's docs. They mention "are related to the methods discussed above" This is fairly ambiguous use of the english language, but in practice it means that reloadRows... only works inbetween beginUpdates and endUpdates.
  • William Jockusch
    William Jockusch about 13 years
    I tried wrapping it. Still the same behavior. Then I wrapped one of my earlier calls to reloadData as you suggested. And that fixed it.
  • amattn
    amattn about 13 years
    Glad you solved it. Somewhat curious though as reloadData is the only reloadXXX method that doesn't need to be wrapped with begin/endUpdates...
  • William Jockusch
    William Jockusch about 13 years
    It appears I was mistaken, still had the second reload in there. Still searching . . .
  • tc.
    tc. about 13 years
    IME, you only need to wrap it in beginUpdates/endUpdates if you're performing multiple updates.