The power of UITableView to discard all reusable cells

I have a UITableView where I have the backgroud color set via

UIView *myView = [[UIView alloc] init]; if ((indexPath.row % 2) == 0) myView.backgroundColor = [UIColor greenColor]; else myView.backgroundColor = [UIColor whiteColor]; cell.backgroundView = myView; [myView release]; 

The problem that I find is that when I edit the table (via setEditing: YES ...), some cells of the same color are immutable next to each other. How to make UITableView completely redraw. reloadData does not do an excellent job.

Is there any deep cleaning?

+4
source share
5 answers

I had this problem, so I will tell you how I solved it:

You can use a boolean flag (for example, it is called needsRefresh ) to control the behavior of creating a cell in -cellForRowAtIndexPath :

Example:

 - (UITableViewCell*) tableView:(UITableView *) tableView cellForRowAtIndexPath:(NSIndexPath*) indexPath { UITableViewCell *cell = [tableView dequeueResuableCellWithIdentifier:SOME_ID]; if(!cell || needsRefresh) { cell = [[[UITableViewCell alloc] init....] autorelease]; } //..... return cell; } 

So, when you need a hard reset, set the needsRefresh flag to YES . Just like a pimple.

+5
source

For me, the accepted answer didn’t really work, since I had no idea when to set Refresh needs back to YES.

What worked for me:

  - (UITableViewCell*) tableView:(UITableView *) tableView cellForRowAtIndexPath:(NSIndexPath*) indexPath { UITableViewCell *cell = [tableView dequeueResuableCellWithIdentifier:customCellIdentifier]; if(nil == cell) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:customCellIdentifier]; } //..... return cell; } 

And then you change the value of customCellIdentifier when you need to. This way, cells can also be reused if you go back to the original cell ID.

+3
source

The accepted method seems dirty, it just creates a bunch of new cells that are stored along with the bad ones. Here are a few solutions depending on your situation:

1. Firstly, for the situation described in the question, you should not reset your cells and create new views in each cycle. You need to mark your view and then return it when from the cell, when you get the reuse cell:

 - (UITableViewCell*) tableView:(UITableView *) tableView cellForRowAtIndexPath:(NSIndexPath*) indexPath { UITableViewCell *cell = [tableView dequeueResuableCellWithIdentifier:SOME_ID]; if(!cell) { cell = [[UITableViewCell alloc] init]; UIView *myView = [[UIView alloc] init]; cell.backgroundView = myView; [myView setTag:5]; //<------ } UIView *myView = [cell viewWithTag:5]; //<------ if ((indexPath.row % 2) == 0) myView.backgroundColor = [UIColor greenColor]; else myView.backgroundColor = [UIColor whiteColor]; return cell; } //then just reload the tableview. 

2. ... or even better, why not just use the backgrouncolor for the cells and update it without creating a view.

3. The surefire way to really clear old cached cells is to simply recreate the UITableView object.

4. In most cases, you do not need to destroy these cells, just keep track of your items and update them after receiving the reused cell. You can mark all your elements, save a link to them in an array, find them in the hierarchy of views ... Im Of course, this is a bunch of other ways.

5. heres one liner to immediately clean all cells, although it is not the best practice to mess with the insides of objects like this as they might change in future versions:

 [(NSMutableDictionary*)[tableview valueForKey:@"_reusableTableCells" ] removeAllObjects]; 
+1
source

I was able to solve this problem by adding an update variable to the table data source. I used a dictionary for each cell, but there is an additional key called @ "refresh": @ "1" indicating that the cell needs updating. After updating it, I set the value of this key to "0". Therefore, whenever the table is reloaded, make sure that the key returns to "0" again.

0
source
 #define TABLE_VIEW_CELL_DEFAULT_ID @"cellIdentifier" @property (nonatomic, strong) NSString *tableViewCellIdentifier; @property (nonatomic) NSUInteger tableViewCellIdentifierCount; // By using a different cell identifier, this effectively flushes the cell // cache because the old cells will no longer be used. - (void) flushTableViewCellCache { self.tableViewCellIdentifierCount++; self.tableViewCellIdentifier = [NSString stringWithFormat:@"%@%i", TABLE_VIEW_CELL_DEFAULT_ID, self.tableViewCellIdentifierCount]; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { MyTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:self.tableViewCellIdentifier]; if (cell == nil) { cell = [[MyTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:self.tableViewCellIdentifier]; } // rest of method... } 
0
source

Source: https://habr.com/ru/post/1314986/


All Articles