重用UITableViewCell的问题

She*_*lam 1 iphone cocoa-touch objective-c uitableview

我有一个UITableView,当用户滚动时重新使用单元格.所有内容都会显示并滚动正常,除非用户单击实际行,突出显示的单元格会显示另一个单元格中的某些文本.我不确定为什么.

#define IMAGE_TAG 1111
#define LOGIN_TAG 2222
#define FULL_NAME_TAG 3333

// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    static NSString *CellIdentifier = @"Cell";

    STUser *mySTUser = [[[STUser alloc]init]autorelease];
    mySTUser = [items objectAtIndex:indexPath.row];

    AsyncImageView* asyncImage = nil;
    UILabel* loginLabel = nil;
    UILabel* fullNameLabel = nil;

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
    }
    else {
        asyncImage = (AsyncImageView *) [cell.contentView viewWithTag:IMAGE_TAG];
        loginLabel = (UILabel *) [cell.contentView viewWithTag:LOGIN_TAG];
        fullNameLabel = (UILabel *) [cell.contentView viewWithTag:FULL_NAME_TAG];
    }

    // Configure the cell...

    cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;

    CGRect frame = CGRectMake(0, 0, 44, 44);
    asyncImage = [[[AsyncImageView alloc]initWithFrame:frame] autorelease];
    asyncImage.tag = IMAGE_TAG;
    NSURL* url = [NSURL URLWithString:mySTUser.avatar_url_large];
    [asyncImage loadImageFromURL:url];
    [cell.contentView addSubview:asyncImage];

    loginLabel.tag = LOGIN_TAG;
    CGRect loginLabelFrame = CGRectMake(60, 0, 200, 10);
    loginLabel = [[[UILabel alloc] initWithFrame:loginLabelFrame] autorelease];
    loginLabel.text = [NSString stringWithFormat:@"%@",mySTUser.login];
    [cell.contentView addSubview:loginLabel];

    fullNameLabel.tag = FULL_NAME_TAG;
    CGRect fullNameLabelFrame = CGRectMake(60, 20, 200, 10);
    fullNameLabel = [[[UILabel alloc] initWithFrame:fullNameLabelFrame] autorelease];
    fullNameLabel.text = [NSString stringWithFormat:@"%@ %@",mySTUser.first_name, mySTUser.last_name]; //[NSString stringWithFormat:@"%@",mySTUser.login];
    [cell.contentView addSubview:fullNameLabel];    


    return cell;
}
Run Code Online (Sandbox Code Playgroud)

dra*_*ard 6

该行分配一个对象然后丢弃它.不要分配您不会使用的项目.

STUser *mySTUser = [[[STUser alloc]init]autorelease];
mySTUser = [items objectAtIndex:indexPath.row];
Run Code Online (Sandbox Code Playgroud)

相反,只需声明一个变量并使用它.

STUser *mySTUser;
mySTUser = [items objectAtIndex:indexPath.row];
Run Code Online (Sandbox Code Playgroud)

此行创建一个新对象并将其分配给单元格,但每次使用单元格时都会发生.

asyncImage = [[[AsyncImageView alloc]initWithFrame:frame] autorelease];
[cell.contentView addSubview:asyncImage];
Run Code Online (Sandbox Code Playgroud)

相反,将所有addSubview行放在创建单元格的if条件中.

if (cell == nil) {
    CGRect frame = CGRectMake(0, 0, 44, 44);
    CGRect loginLabelFrame = CGRectMake(60, 0, 200, 10);
    CGRect fullNameLabelFrame = CGRectMake(60, 20, 200, 10);
    cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
    asyncImage = [[[AsyncImageView alloc]initWithFrame:frame] autorelease];
    [cell.contentView addSubview:asyncImage];
    loginLabel = [[[UILabel alloc] initWithFrame:loginLabelFrame] autorelease];
    [cell.contentView addSubview:loginLabel];
    fullNameLabel = [[[UILabel alloc] initWithFrame:fullNameLabelFrame] autorelease];
    [cell.contentView addSubview:fullNameLabel];    
    asyncImage.tag = IMAGE_TAG;
    loginLabel.tag = LOGIN_TAG;
    fullNameLabel.tag = FULL_NAME_TAG;
} else ...
Run Code Online (Sandbox Code Playgroud)

唯一应该发生的事情就是if if block是对每个单元格更改的属性的赋值,比如[asyncImage loadImageFromURL:url];将文本分配给标签.

此行为可能的nil对象分配属性,然后分配对象.

loginLabel.tag = LOGIN_TAG;
loginLabel = [[[UILabel alloc] initWithFrame:loginLabelFrame] autorelease];
Run Code Online (Sandbox Code Playgroud)

而是在创建对象后分配属性.

loginLabel = [[[UILabel alloc] initWithFrame:loginLabelFrame] autorelease];
loginLabel.tag = LOGIN_TAG;
Run Code Online (Sandbox Code Playgroud)

此行使用格式化字符串,其中一个简单的赋值即可.

loginLabel.text = [NSString stringWithFormat:@"%@",mySTUser.login];
Run Code Online (Sandbox Code Playgroud)

相反,假设mySTUser.login,只需直接分配它.

loginLabel.text = mySTUser.login;
Run Code Online (Sandbox Code Playgroud)