开发者

Force UITableView to dump 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 = myVie开发者_运维知识库w;
[myView release];

The problem I find is that when I edit a table (via setEditing:YES...) some cells of the same color invariable are next to each other. How do I force UITableView to fully redraw. reloadData is not doing a great job.

Is there are deep-cleaning redraw?


I had this issue before so I'll share with you how I solved it:

You can use a boolean flag (say it's called needsRefresh) to control the behavior of cell creation in -cellForRowAtIndexPath:

An 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 reload, set the needsRefresh flag to YES. Simple as a pimple.


For me the accepted answer didn't really work since I had no idea when to set the needsRefresh back to YES.

What worked for me was:

 - (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 customCellIdentifier value whenever you need to. This way the cells are also still reusable if you switch back to the original cell identifier.


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

1. first, for the situation described in the question you should not dump your cells and create new views on every cycle. You need to tag your view and then get it back when from the cell when you get a 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 cell backgrouncolor and update that without creating a view.

3. A sure way to really clear out old cached cells it to simply recreate the UITableView object.

4. In most cases you dont need to destroy these cells, just keep track of your elements and update them after getting the reusable cell.You can tag all your elements, keep a array reference to them, find them thought the view hierarchy... Im sure theres a bunch of other ways.

5. heres a one liner to directly purge all cells, although not best practice to mess with the internals of objects like this as they might change in future versions:

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


I was able to solve this by adding a refresh variable to the table datasource. I used a dictionary for each cell, but there's an extra key called @"refresh":@"1", indicating the cell needs refreshing. Once it's updated, I set that key's value to @"0". So whenever the table is reloaded, make sure the key goes back to @"0" again.


#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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜