I have collectionview cells that are updated dynamically by long running jobs.
I want to be able to delete cells (representing jobs) from the view but preserve relationship between the long running job and the original index path which should display that jobs results.
I've tried using
self.collectionView performBatchUpdates:^{
[self.dataSource collectionview:self deleteItemsFromDataSourceAtIndexPaths:#[path]];
[self.collectionView deleteItemsAtIndexPaths:#[path]];
} completion:nil];
but i am having problems updating all the relationships to the new index paths that the jobs should relate to.
I have also tried assigning cells an identifier to a job and looking up the cell with the jobs identifer, but this approach doesn't work as the cell for the job can change when scrolling.
I think it would be easiest to set the size of the collectionview cell to 0 in the delegate method
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
but was not able to set the size to zero
Any way around this.
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?
I have a UISegmentedControl with 2 segments. I'm loading JSON data into a table view and each segment has different data. I first load the view and the default first segment shows up - data is there and cell height is perfect. When I tap on the second segment, all is well, the data loads properly and the cell height now matches this set of data. However, when I go back to the first segment the cell height is from the second, which is not what I want. Ideally the cells will resize for the first segment data like it originally did.
When I return to the first segment, how can I re-adjust the cell height so the data displays properly again?
You should implement
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
delegate method. and return the hight you want there.
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.
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?
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