views:

358

answers:

4

I am using a UITableView to display the results of a series of calculations. When the user hits 'calculate', I add the latest result to the screen. When I add a new cell, the UITableViewCell object is added to an array (which is indexed by tableView:cellForRowAtIndexPath:), and then I use the following code to add this new row to what is displayed on the screen:

[thisView beginUpdates];
[thisView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation: UITableViewRowAnimationFade];
[thisView endUpdates];

This results in the new cell being displayed. However, I then want to immediately scroll the screen down so that the new cell is the lowermost cell on-screen. I use the following code:

[thisView scrollToRowAtIndexPath:newIndexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];

This almost works great. However, the first time a cell is added and scrolled to, it appears onscreen only briefly before vanishing. The view scrolls down to the correct place, but the cell is not there. Scrolling the view by hand until this invisible new cell's position is offscreen, then back again, causes the cell to appear - after which it behaves normally. This only happens the first time a cell is added; subsequent cells don't have this problem. It also happens regardless of the combination of scrollToRowAtIndexPath and insertRowsAtIndexPath animation settings.

EDIT: I've now started inserting cells at the second-to-last position of the table, rather than the end, and the problem still occurs - when first inserted, a cell is 'invisible' until it goes offscreen and comes back on again. What could be causing this, and how can I force the cell to be drawn as soon as it is added to the table?

+1  A: 

Try to scroll with some time shift after cell update via NSTimer or performSelector:withDelay:. It can help but to fix all problems I think there need to do more work.

Skie
This helped previously, but now I am inserting rows to the middle of the table and it doesn't make a difference. Any suggestions?
Daniel I-S
A: 

I used what Skie suggested to avoid the problem in the following way:

Immediately after adding the row:

[self performSelector:@selector(scrollToDesiredArea:) withObject:newIndexPath afterDelay:0.4f];

This called the following:

-(void)scrollToDesiredArea:(NSIndexPath *)indexPath{
     UITableView *thisView = (UITableView*)self.view;
     [thisView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];
}

The delay of 0.4s seems to be sufficient to avoid the glitching; any less and it still happens. It may have to be different on varying models of iPhone hardware, though - I only tested on emulator.

Daniel I-S
This worked reasonably well when I was just adding a cell to the end. However, now I am inserting a cell in the midst of the other cells it just fails to draw until it has been scrolled offscreen and back. The cells below it slide down, leaving an empty space through which I can see the grouped table background. Once this space is scrolled offscreen and back, it reveals itself as the cell that I added - and works perfectly from then on.
Daniel I-S
+3  A: 
TechZen
The rows of my table are held in nested arrays. An outer NSMutableArray contains one inner NSMUtableArray for each section. Each section NSMutableArray contains the cells for that section. `numberOfSectionsInTableView:` returns the number of section arrays, and `tableView:numberOfRowsInSection:' returns the number of cells in the relevant section array. `cellForRowAtIndexPath` uses the section and row numbers to locate the relevant row in my array structure, and returns that.
Daniel I-S
I'm not looking to have more than a few rows, let alone a few dozen. I'll look into a redesign, but I would like to have a short-term solution too.
Daniel I-S
Short-term, you have to make sure that datasource reflects the addition of the results cell when it returns the number of sections and rows. I would call `-[UITableView reload]` after you add the cell to the data array. That should cause the tableview to update itself with the proper number of sections and rows which will let it display itself properly. However, you are always going to have trouble with this design and it will always cause you a lot of extra work.
TechZen
+1  A: 

The glitches may be caused because a UITableView considers itself the owner of any UITableViewCell instances it is displaying, and reuses them as needed. Part of that process is calling prepareForReuse on the cell. Since you are keeping the cells in an array, you do not want them reused. Try implementing an empty prepareForReuse in your UITableViewCell class. Or just create cells dynamically in tableView:cellForRowAtIndexPath: as apple recommends.

drawnonward