简体   繁体   中英

iOS tableView cell caching issues not loading every cell

I'm having a bit of difficulty understanding what is going wrong and how to fix this.

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell == nil)
{
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];


    NSUInteger row = [indexPath row];

    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    cell.selectionStyle = UITableViewCellSelectionStyleBlue;

    UILabel *where = [[UILabel alloc] initWithFrame:CGRectMake(88.0, 0.0, 155.0, 22.0)];
    where.text = [delegate.destinationArray1 objectAtIndex:row];
    where.font = [UIFont fontWithName:@"Helvetica" size:12.0];
    where.textColor = [UIColor blueColor];
    [cell.contentView addSubview:where];
    return cell;
}

This doesn't work properly but this does:

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell == nil)
{
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}

NSUInteger row = [indexPath row];

    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    cell.selectionStyle = UITableViewCellSelectionStyleBlue;

    UILabel *where = [[UILabel alloc] initWithFrame:CGRectMake(88.0, 0.0, 155.0, 22.0)];
    where.text = [delegate.destinationArray1 objectAtIndex:row];
    where.font = [UIFont fontWithName:@"Helvetica" size:12.0];
    where.textColor = [UIColor blueColor];
    [cell.contentView addSubview:where];
    return cell;
}

They both get populated by "delegate.destinationArray1" but when all the code is inside the curly braces of

if(cell == nil)

the list gets unordered and repeats cells and misses some out. I can't use the latter way as it creates a MASSIVE memory leak when scrolling.

Any ideas?

I did the exact same thing when I started using UITableViews. The reason for the memory leak is that in the second implementation (the one that works) you are actually creating every cell, every single time. Let me try to explain a bit more.

You never want to set content of a cell between the (cell == nil) . The reason for this is the reuseIdentifier . If the table needs to display a new cell it will grab one and see if it has already been alloced/inited. If it has it will just use it. If that is the case the content will already be set in the cell you grabbed and you are not telling it to set it any differently.

between the (cell == nil) only create and establish the view. Not the content. All content should be set after. So then no matter what cell it grabs it can always set the content. So this is what you want:

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
     static NSString *CellIdentifier = @"Cell";

     UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
     if(!cell) // or (cell == nil)
     {
          cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
          cell.selectionStyle = UITableViewCellSelectionStyleBlue;
          UILabel *where = [[UILabel alloc] initWithFrame:CGRectMake(88.0, 0.0, 155.0, 22.0)];
          where.font = [UIFont fontWithName:@"Helvetica" size:12.0];
          where.textColor = [UIColor blueColor];
          where.tag = 1;
          [cell addSubview:where];
     }

     NSUInteger row = indexPath.row;

     UILabel *where = [cell viewWithTag:1];
     where.text = [delegate.destinationArray1 objectAtIndex:row];

     return cell;
}

I just coded this in StackoverFlow so sorry if there are any small syntax errors.

The cell object is reused or created by the first statement. After checking cell for nil and creating a cell, you must not create another cell.

So delete the line

cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];

which comes after

NSUInteger row = [indexPath row];

and you'll work with the correct cell object.

When the tableview reuses cells it is based on the CellIdentifier. The tableview doesn't care what attributes you've set on the cell. In the first case the reuse it happening and it recognizes a cell it can use but that cell has the wrong information on it.

What I do is subclass UITableViewCell and do all the work inside of that class. Here is a quick snippet

@implementation AlertCell

//Custom init method
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier withHeight:(float)height {
//Whatever you need to do
}

//Place the views
- (void)layoutSubviews {
}

//Custom Setter method
- (void)setAlert:(CWAlert *)incomingAlert withAssets:(NSDictionary *)assets {
}

@end

Then you do something like this

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier;
CWAlertCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];

if (!cell) {
    cell = [[AlertCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier withHeight:[self convertAssetsLengthToCellHeight:assetsLength]];

    UIView *selectedView = [[UIView alloc] init];
    selectedView.backgroundColor = [UIColor colorWithHexString:@"F6F6F6"];
    cell.selectedBackgroundView = selectedView;
}

NSDictionary *alertInfo = [AlertCell getNeededCellAssets:alert];
[cell setAlert:alert withAssets:alertInfo];
return cell;
}

I can show more code from the subclass if needed.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM