35

I got a tricky problem regarding updating my TableView, i get different results using different methods of updating it, let me explain:

Situation 1: I use [tbl reloadData]; where tbl is my TableView, to update the TableView - works as intended.

Situation 2: I use:

[tbl beginUpdates];
[tbl reloadRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationRight];
[tbl endUpdates];

Where tbl is my TableView, and indexPaths is an array containing all the indexPaths present in the TableView. Now the array is fine, it contains all the correct indexPaths (double and triple checked) but for some reason - this does not work as intended.

Now I realize that this is an X-Y problem (where I ask for Y but my problem is really X because I think solving Y will solve X) and thats only because I feel it's a bit complicated explaining X (the consequence of said above problem) in an easy way, so I'd rather refrain from that if possible.

So, down to my question: Is there a difference between the two ways of updating the TableView (aside from the animation bit of course) or should I suspect the problem to lay elsewhere?

EDIT: Okay, I'll try to explain what the symptoms are:

In the cellForRowAtIndexPath-method I add a button to each cell with an assigned tag which is equal to the cell's indexPath row, like such:

btn.tag = indexPath.row;

The reason I do this is so I can identify each button as they all call the same function:

- (void)btnPressed:(id)sender

When I then update the cells - because some values in the cells have changed - Situation 1 makes everything work fine, Situation 2 however - mixes up the tags so the next time one of the buttons are pressed, they no longer have the correct tags.

The mix-up does appear random to me, but the randomization occurs differently depending on which cells button I press first. I hope this clarifies my problem.

Cœur
  • 32,421
  • 21
  • 173
  • 232
Tobias Tovedal
  • 681
  • 2
  • 8
  • 14
  • 1
    "i get different results," "this does not work as intended." In what way? – TigerCoding Nov 17 '11 at 20:48
  • Well, every cell gets a button upon creation , with a tag, where `the button tag = the index path row`. In Situation 1 the button gets the correct tag, in Situation 2 - it does not. – Tobias Tovedal Nov 17 '11 at 20:55

3 Answers3

25

From the UITableView documentation

beginUpdates
Begin a series of method calls that insert, delete, or select rows and sections of the receiver.

That means, you should not use this unless you are inserting, deleting or selecting. You are doing neither of these.

Also, you should end beginUpdates with endUpdates, not reloadData. Documentation:

This group of methods must conclude with an invocation of endUpdates.

Mundi
  • 77,414
  • 17
  • 110
  • 132
  • 1
    Ah, yes the `reloadData`-bit was a typo in my post - my bad. – Tobias Tovedal Nov 17 '11 at 20:56
  • Okay, than that concludes the difference between reloadData and beginUpdates/endUpdates, but I really can't se how theses difference should affect my outcome in the way it does. I realize I've been a bit vague in describing the consequences, I'll update my original question in a couple of minutes. – Tobias Tovedal Nov 17 '11 at 21:00
  • Try to drop `beginUpdates` and `endUpdates`. They do not belong around `updateRowsAtIndexPaths`. – Mundi Nov 17 '11 at 21:02
  • 1
    Mundi - with the `beginUpdates`and `endUpdates`-tags the values in the cells ARE updated correctly, using `[tbl reloadRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationRight];`alone does not seem to update anything unfortunately. – Tobias Tovedal Nov 17 '11 at 21:13
  • Interesting. In one of my projects this works without these. I will investigate. – Mundi Nov 19 '11 at 10:12
  • @TobiasTovedal Is it cleared? Is it necessary or not? – Ixx Mar 23 '15 at 13:47
  • @Ixx, the issue was never resolved completely, however the title question seem to have been answered. – Tobias Tovedal Jul 13 '15 at 17:20
7

The first difference between reloadData and reloadRowsAtIndexPaths is that there are 2 UITableViewCell objects allocated simulteaneosuly for the same indexPath when doing reloadRowsAtIndexPaths (because the tableview 'blends' in the the new cell) . This is sometimes not foreseen by the code in cellForRowAtIndexPath .The surprise comes from the fact that even if a cell was already allocated for a particular cell identfier the table view does not give you back this cell in dequeueReusableCellWithIdentifier when calling reloadRowsAtIndexPaths, instead it returns nil. In contradiction reloadData reuses the cells it already allocated .

The 2nd difference is that endUpdates after reloadRowsAtIndexPaths directly calls cellForRowAtIndexPath (if you set a breakpoint there,endUpdates is visible in the stack trace) whereas reloadData schedules the calls to cellForRowAtIndexPath at a later time (not visible in the stack trace).

However you would need to post a bit more code to give us insight what you are doing there. In principle the indexPaths of the new cells are identical to the old ones also with reloadRowsAtIndexPaths as long as you don't delete or insert rows.

Leo
  • 551
  • 5
  • 17
  • Thank you for your answer Leo. It's been a few years and I don't remember what happened to this project however I doubt I ever solved it, hopefully this Q and the answers given by you and @Mundi help someone else with similar issues. – Tobias Tovedal Jul 13 '15 at 17:19
2

Call this method if you want subsequent insertions, deletion, and selection operations (for example, cellForRowAtIndexPath: and indexPathsForVisibleRows) to be animated simultaneously.

I think this is what you want. beginUpdates & endUpdates can change the UItableview with animation.

gfxcc
  • 31
  • 3