iOS:未使用重用标识符清除单元格内容

Posted

技术标签:

【中文标题】iOS:未使用重用标识符清除单元格内容【英文标题】:iOS: Cell content not being cleared with reuseidentifier 【发布时间】:2014-01-25 03:26:50 【问题描述】:

我正在尝试使用列出 UILabel 中的数组的单元格构建一个表格。因此,每个单元格的大小和标签数量由该数组中的对象数量决定。但是,我遇到了一个问题,内容最初输入正确,但随着表格单元格在滚动过程中被回收,内容不清晰。

这是我的整个实现。如果有人可以请给我一个解释,说明如何防止标签在回收过程中被保留,我真的很感激。谢谢。

ViewController.h

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController <UITableViewDataSource, UITableViewDelegate> 
    UITableView *tableView;


@end

ViewController.m

#import "ViewController.h"
#import "CustomCell.h"

@interface ViewController () 
    NSArray *myTableArray;


@end

@implementation ViewController

- (void)viewDidLoad

    [super viewDidLoad];

    // Set up View
    self.view = [[UIView alloc] initWithFrame: [UIScreen mainScreen].applicationFrame];
    self.view.backgroundColor = [UIColor whiteColor];
    self.view.clipsToBounds = YES;
    self.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;

    // Set up Table
    CGRect frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
    tableView = [[UITableView alloc] initWithFrame:frame style:UITableViewStylePlain];
    tableView.backgroundColor = [UIColor clearColor];
    tableView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
    tableView.dataSource = self;
    tableView.delegate = self;
    [tableView registerClass:[CustomCell class] forCellReuseIdentifier:@"CustomCell"];
    [self.view addSubview:tableView];

    //Set up dummy array for cells (in my actual app I'm pulling from Core Data)
    NSArray *cell1 = [[NSArray alloc]initWithObjects:@"Some Text", nil];
    NSArray *cell2 = [[NSArray alloc]initWithObjects:@"Different", @"Text", nil];
    NSArray *cell3 = [[NSArray alloc]initWithObjects:@"Lorem...", nil];
    NSArray *cell4 = [[NSArray alloc]initWithObjects:@"Thanks", @"for your", @"help", nil];
    NSArray *cell5 = [[NSArray alloc]initWithObjects:@"A bit more", @"text", nil];
    NSArray *cell6 = [[NSArray alloc]initWithObjects:@"Bunch of", @"junk text", nil];
    NSArray *cell7 = [[NSArray alloc]initWithObjects:@"So long", @"and thanks", @"for all", @"the fish", nil];
    NSArray *cell8 = [[NSArray alloc]initWithObjects:@"Ipsum..", nil];
    NSArray *cell9 = [[NSArray alloc]initWithObjects:@"Peter Pan", @"killed", @"The Lost Boys", nil];
    NSArray *cell10 = [[NSArray alloc]initWithObjects:@"All Dogs", @"Go to Heaven", @"Disney", nil];
    myTableArray = [[NSArray alloc]initWithObjects:cell1, cell2, cell3, cell4, cell5, cell6, cell7, cell8, cell9, cell10, nil];
    NSLog(@"%@",myTableArray);



- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 
    return myTableArray.count;


- (CGFloat)tableView:(UITableView *)table heightForRowAtIndexPath:(NSIndexPath *)indexPath 

    NSArray *arr = [myTableArray objectAtIndex:indexPath.row];
    return 60 * arr.count;


- (UITableViewCell*)tableView:(UITableView *)table cellForRowAtIndexPath:(NSIndexPath *)indexPath 
    static NSString *cellIdentifier = @"CustomCell";
    CustomCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];

    if (!cell)
        cell = [[CustomCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];

    // Set up the labels
    [cell setLabels:myTableArray[indexPath.row]];

    return cell;



@end

CustomCell.h

#import <UIKit/UIKit.h>

@interface CustomCell : UITableViewCell
- (void)setLabels:(NSArray *)labels;
@end

CustomCell.m

#import "CustomCell.h"

@implementation CustomCell

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier

    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) 
        // Initialization code
    
    return self;


- (void)setSelected:(BOOL)selected animated:(BOOL)animated

    [super setSelected:selected animated:animated];

    // Configure the view for the selected state


- (void)setLabels:(NSArray *)labels 
    int labelHeight = 60;
    int y = 0;
    for (NSString *string in labels) 
        UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(10, y, self.bounds.size.width-20, labelHeight)];
        label.text = string;
        label.font = [label.font fontWithSize:20];
        y += labelHeight;
        [self.contentView addSubview:label];
    

@end

【问题讨论】:

【参考方案1】:

在你的CustomCell.m

- (void)prepareForReuse 
    [super prepareForReuse];
    for(UIView *subview in [self.contentView subviews]) 
        [subview removeFromSuperview];
    

prepareForReuse 是一种在单元格上调用的方法,因为表格视图正在将它们出列以供重用。

我假设您已将实际操作最小化为一个非常简单的示例,因为否则,正如 Leo Natan 所建议的,您应该简单地使用现有标签。

【讨论】:

是的,我有。我正在开发的应用程序不仅仅是标签,我只是将其构建为隔离问题的快速示例。谢谢。【参考方案2】:

那是因为您要添加一个新的 UILabel 子视图,而没有删除旧的。

为什么要添加新标签?使用已经存在的标签。由于您使用的是UITableViewCellStyleDefault,因此该单元格已经包含多个标签。请改用self.textLabel.text = string

如果您希望继续使用自定义标签,您应该删除单元格的prepareForReuse 中的所有子视图(不要忘记调用prepareForReuse 的超级实现)。请记住,由于您已将单元格定义为 UITableViewCellStyleDefault,因此您不应删除其他子视图。

【讨论】:

好吧,我正在添加新标签,因为单元格没有固定数量。因此,如果出现一个单元格有 30 个标签的情况,我希望它能够对此做出响应,而无需为类似 100 个不同的单元格创建重用标识符。 @IanGray 在这种情况下,您应该删除以前的标签,因为它们不再需要。【参考方案3】:

在重复使用的单元格中添加标签之前,您应该删除所有标签。

- (UITableViewCell*)tableView:(UITableView *)table cellForRowAtIndexPath:(NSIndexPath *)indexPath 
    static NSString *cellIdentifier = @"CustomCell";
    CustomCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];

    if (!cell)
        cell = [[CustomCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];

    for (UIView * subView in [cell.contentView subviews]) 
        if ([subView isKindOfClass:[UILabel class]]) 
            [subView removeFromSuperview] ;
        
    

    // Set up the labels
    [cell setLabels:myTableArray[indexPath.row]];

    return cell;

【讨论】:

鉴于我们正在讨论自定义单元格类,您为什么不使用prepareForReuse 是的,最好在prepareForReuse做,不过我之前没用过。

以上是关于iOS:未使用重用标识符清除单元格内容的主要内容,如果未能解决你的问题,请参考以下文章

UITableView 单元格内容未正确显示

iOS8“现在”改变动态单元格的高度,重新内部单元格内容

vba中如何将单元格内容强制转换为文本类型?

iOS:UICollectionViewCell 动画部分更改单元格内容

表删除操作删除单元格内容但不删除单元格本身?

vba中怎么用代码将单元格内容转换为文本类型?