I have a few UITableView's in my project, and sometimes I need to swap cells between them. Cells are complex enough and it's take a lot of time to re-create them each time I move them from one table to another, so I create its once, keep in array and pick up necessary cells in cellForRowAtIndexPath Moving cells between tables looks something like this:
NSIndexPath* pathForMovedCell = [firstTableView indexPathForCell:movedCell];
[firstTableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:pathForMovedCell] withRowAnimation:UITableViewRowAnimationFade];
//There is some delay for show animation and switch between view controllers
[secondTableView insertRowsAtIndexPaths:[NSArray arrayWithObject:pathForMovedCell] withRowAnimation:UITableViewRowAnimationFade];
This code works pretty good, but sometimes (always, if delay less then 0,33 seconds) cell is not drawn on secondTableView. It normally inserted, and will be drawn if scroll them from visible area and return back. I think it's happens if inserting occurs before deletion animation ends. If I made short delay, cells disappears often, and I don't want to leave big time reserve, because it looks like lags, so I want to solve this problem correctly. I tried to add [cell setNeedsDisplay] before returning cell from cellForRowAtIndexPath, but it doesn't work.
Any suggestion?
Related
I want to calculate the size of a cell that I've just added to an NSOutlineView. To do that, I add it to my data source, and then call reloadData on the NSOutlineView. For some reason, however, I can't examine the cell after reloadData for any but the very first row. The code looks like this:
[m_dataSource add:...]; // first add item to my data source
[m_outlineView reloadData];
int nRows = (int) [m_outlineView numberOfRows];
NSCell *cell = [m_outlineView preparedCellAtColumn:0 row:nRows-1];
NSSize size = [cell cellSize];
For some reason, nRows is always 1 here, no matter how many rows I add. Thus, I can only ever query the size of the first cell in the very first row.
The behaviour I see might be related to the fact that the very first row is an expandable row and all other rows are children of the very first row. However, I have checked that
- (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item;
correctly returns YES for the item. Everything also appears correctly in the NSOutlineView. It's just that numberOfRows doesn't seem to get updated even though I call reloadData just before it.
Any ideas what's wrong here?
In my Example i 've got 2 Sections with 1 Row at the Start. It someone clicks on the first row of a section i insert all other rows of this section:
[tableView insertRowsAtIndexPaths:indexArray withRowAnimation:UITableViewRowAnimationTop];
This works fine, but i need to update the Background of the first row. This works too, but i need to relayout the first row. I have tried setNeedsDisplay and setNeedsLayout, but it don't worked. A reloadDate shows the right background, but it destroys the sliding effect.
I know that i can update a Row with one of this:
[tableView reloadRowsAtIndexPaths:indexArrayReload withRowAnimation:UITableViewRowAnimationFade];
[tableView reloadRowsAtIndexPaths:indexArrayReload withRowAnimation:UITableViewRowAnimationNone];
But they change the hight of the Row temporary. I need a real fading effect or a reload without animation.
Here is the Picture of the Situation:
Edit: I 've made a video:
This shows the Problem!
This is the solution:
[tableView beginUpdates];
...
[tableView endUpdates];
I fond it in another thread.
I have a custom UITableViewCell that seems to appear multiple times on my table before I even start scrolling. It seems dequeueReusableCellWithIdentifier isn't working properly. Here's my cell:
MyCustomCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[MyCustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
... setup ...
}
When I call reloadRowsAtIndexPaths: on my tableView, for some reason it doesn't dequeue that cell and it recreates the new one. Then when I scroll back up and then down again, sometimes my first cell dequeues, sometimes the second cell dequeues. MyCustomCell is basically a textfield so depending on which one dequeues, the text has different data each time.
Is there something more I should be doing in my custom cell? Thanks in advance.
You mention reloadRowsAtIndexPaths: in your question, but the method is actually reloadRowsAtIndexPaths:withRowAnimation:. The fact that the reload can be animated matters. For example, to animate UITableViewRowAnimationLeft, the table view needs to slide out an old cell while sliding in a new cell. Both the old and new cells are on screen simultaneously, so the table view can't just use the same UITableViewCell object for both. That's why “it doesn't dequeue that cell and it recreates the new one”. It needs a new one because the old one is still visible.
You need to make sure that when you receive a tableView:cellForRowAtIndexPath: message, you fully initialize the cell (whether dequeued or newly created) to show the data for the requested row, and only the data for the requested row.
Also, you can't keep your own mapping from the row's indexPath to the cell, because (during animations) there may be two cells for the same row. Instead, if at any time you need to get the cell that is currently showing the data for a row, you need to ask the table view for the cell by sending it a cellForRowAtIndexPath: message.
From the code you show, it looks as if you only set up your cell's content when a new one is created. Since there's no way of knowing which cell you'll be given from the cache, you need to configure the cell whether it's new or one that's being re-used.
My table view covers part of the view. If I have 20 objects, I am displaying all of them in a tableview. But I want to know that how many cell are loaded that are visible to the user.
(i.e. first 5 cells data is visible for me: when I scroll down, the remaining cells will load. Here I want to know without scrolling how many cell are loaded.)
Is this possible?
You can use [tableView visibleCells] count], which returns numbers of the table cells that are visible, if I understand correctly what you want.
The below code will give you the array of indexpath of cells currently visible
NSArray *visiblePaths = [self.tableView indexPathsForVisibleRows];
after getting the index path you can easily access the cell at a particular indexpath
Its usually : (tableView's height / cell row height ) + 1
Can you take the size of the visible part of the table, and then the size of one cell, and divide them to know how many of them fit in the screen?
I have a table view with cells that can be deleted. When a cell is deleted, I would like to display a deletion animation such as UITableViewRowAnimationFade. The problem is that my table view's cells have alternating background colors, so I need to -reloadData after the animation completes to fix the colors of all cells below the deleted cell.
So, incase you haven't read this far, I need a way to run some code after a table view animation is complete. I am currently using performSelector:withObject:afterDelay: and hardcoding an approximation of the animation delay. This method works, but there must be a better way to do it:
NSIndexPath * path = [listTable indexPathForCell:deletingCell];
NSArray * indexPaths = [NSArray arrayWithObject:path];
[listTable deleteRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationFade];
[listTable performSelector:#selector(reloadData) withObject:nil afterDelay:0.35];
In this case I am assuming that UITableViewRowAnimationFade will take less than 0.35 seconds to complete.
You could also use NSTimer with the same delay (although unneeded, -performSelector:withObject:afterDelay: works fine).
Another option would be to loop through the cells after deletingCell (path) and redraw them, or add the index paths to an array and call reloadRowsAtIndexPaths:withRowAnimation: as shown below. Then you could also use the UITableViewRowAnimationFade
- (void)reloadRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation