繁体   English   中英

如何避免UITableViewCell在TableView滚动时重复添加自定义标签?

[英]How to avoid UITableViewCell repeat add custom label when TableView scrolling?

我创建一个自定义单元格:

#import <UIKit/UIKit.h>
#import "RecruitmentResumeEntity.h"

@interface RecruimentListItemCell : UITableViewCell
@property (nonatomic, strong) RecruitmentResumeEntity *entity;
@end

在.m文件中设置实体方法时,我添加了三个标签:

-(void)setEntity:(RecruitmentResumeEntity *)entity {

   _entity = entity;

   float labelHeight = 17;

   CGRect frame = CGRectMake(64, 45, 0, labelHeight);
   UILabel *cityLabel = [self createTagLabelWithFrame:frame text:_entity.city backgroundColor:@"#e5986f"];
   [self.contentView addSubview:cityLabel];

   UILabel *workExperienceLabel = [self createTagLabelWithFrame:CGRectMake(cityLabel.x+cityLabel.width +10, cityLabel.y, 0, labelHeight) text:[NSString stringWithFormat:@"%@年",_entity.workExperience] backgroundColor:@"#81A0D7"];
   [self.contentView addSubview:workExperienceLabel];

   UILabel *expectSalaryLabel = [self createTagLabelWithFrame:CGRectMake(workExperienceLabel.x+workExperienceLabel.width +10, workExperienceLabel.y, 0, labelHeight) text:_entity.expectSalary backgroundColor:@"#94C373"];
   [self.contentView addSubview:expectSalaryLabel];
}

在控制器中,cellForRowAtIndexPath方法获取自定义单元格并设置实体。 但是,当我运行应用程序并滚动UITableView时,我发现单元格重复创建了三个标签,而我只希望每个单元格只有三个Label。 我弄错了吗? 谁能帮助我? 等待您的帮助。谢谢。 在此处输入图片说明

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

   RecruitmentResumeEntity *entity = _dataList[indexPath.row];
   RecruimentListItemCell *cell = [tableView dequeueReusableCellWithIdentifier:@"RecruimentListItemCell" forIndexPath:indexPath];
   cell.entity = entity;

   return cell;
}

如果您没有正确地重新使用单元,这似乎是一个问题。

当您调用RecruimentListItemCell *cell = [tableView dequeueReusableCellWithIdentifier:@"RecruimentListItemCell" forIndexPath:indexPath]; 系统会将您认为可以重新使用的单元格显示给它需要显示的下一个单元格的信息,但是您有责任在重新使用它之前为该单元格做好充分准备。

为此,你将必须实现-(void)prepareForReuseRecruimentListItemCell ,在那里你将不得不确保需要在细胞重新填充所有项目都正确重置,这样,当电池可适当填充。

例如,如果在RecruimentListItemCell要添加标签“SampleLable”作为一个子视图,但你不做[SampleLable removeFromSuperView]-(void)prepareForReuse那么每一个细胞的再生时,“SampleLable”将再次被添加到它一遍又一遍,最终您会发现事情看起来不像应该的那样,就像您的“重复创建标签”一样

这是prepareForReuse在我的一个应用程序中的外观:

-(void)prepareForReuse {

[super prepareForReuse];

[_statesView.activityIcon1 setHidden:YES];
[_statesView.activityIcon2 setHidden:YES];

_title.text = nil;
_infoText.text = nil;
_createdTime.text = nil;
_cellType = CustomCellTypeNone;

[_progressView setProgress:0];
}

在这里,您可以看到一些我刚刚设置为nil的项目(并非总是最好的方法),如果需要的话,将它们再次放入。 您会看到我隐藏了activityIcon 1和2。当下一个单元格出现时,如果它需要图标,它只是取消隐藏它们,如果它需要标签,则添加它们。

因此,如果我不删除所有标签,则发生的情况是它们保留在视图中,而下一个单元格可能会添加自己的标签,这将导致您遇到的问题。

您可以将这三个标签设置为RecruimentListItemCell属性,并通过延迟加载对其进行初始化。

- (UILabel *)cityLabel
{
    if (!_cityLabel) {
        _cityLabel = [self createTagLabelWithFrame:frame text:nil backgroundColor:@"#e5986f"];
        [self.contentView addSubview:cityLabel];
    }
    return _cityLabel;
}

- (UILabel *)workExperienceLabel
{
    if (!_workExperienceLabel) {
        _workExperienceLabel = [self createTagLabelWithFrame:CGRectMake(cityLabel.x+cityLabel.width +10, cityLabel.y, 0, labelHeight) text:nil backgroundColor:@"#81A0D7"];
        [self.contentView addSubview:workExperienceLabel];
    }
    return _workExperienceLabel;
}

- (UILabel *)expectSalaryLabel
{
    if (!_expectSalaryLabel) {
        _expectSalaryLabel = [self createTagLabelWithFrame:CGRectMake(workExperienceLabel.x+workExperienceLabel.width +10, workExperienceLabel.y, 0, labelHeight) text:_entity.expectSalary backgroundColor:@"#94C373"];
        [self.contentView addSubview:expectSalaryLabel];
    }
    return _expectSalaryLabel;
} 

而且,您只需在选择器setEntity:为这些标签设置setText即可。

-(void)setEntity:(RecruitmentResumeEntity *)entity {

    _entity = entity;

    float labelHeight = 17;

    [self.cityLabel setText:_entity.city];

    [self.workExperienceLabel setText:[NSString stringWithFormat:@"%@年",_entity.workExperience]];
    self.expectSalaryLabel setText:_entity.expectSalary];
}

为了进行良好的重用,可以覆盖选择器prepareForReuse

- (void)prepareForReuse
{
    [super prepareForReuse];

    _cityLabel.text = nil;
    _workExperienceLabel.text = nil;
    _expectSalaryLabel.text = nil;
}

此外,您可以覆盖选择器layoutSubviews进行布局。

- (void)layoutSubviews {

    [super layoutSubviews];
}

那是因为tableView重用了单元格,所以它重复创建了您的UILabel,您可以在创建它之前删除三个UILabel!

您可以在生成任何单元格之前通过比较cell == nil条件来使用。

static NSString *recruitmentTableIdentifier = @"RecruimentListItemCell";

RecruimentListItemCell *cell = [tableView dequeueReusableCellWithIdentifier:recruitmentTableIdentifier];

if (cell == nil) {
    cell = [[RecruimentListItemCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:recruitmentTableIdentifier];
}

希望,它将成功。
谢谢。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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