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

时间:2016-01-14 03:31:56

标签: ios objective-c uitableview

我创建了一个自定义Cell:

#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];
}

在Controller cellForRowAtIndexPath方法中获取自定义单元格和设置实体。但是当我运行app,滚动UITableView时,我发现单元格重复创建三个标签,我只想让每个单元格只有三个Label。我弄错了什么或丢失了。任何人都可以帮助我吗?等你帮忙。谢谢。 enter image description here

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

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

   return cell;
}

4 个答案:

答案 0 :(得分:4)

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

当您致电RecruimentListItemCell *cell = [tableView dequeueReusableCellWithIdentifier:@"RecruimentListItemCell" forIndexPath:indexPath];时,系统会向您发送一个它认为可以重复使用的单元格来显示它需要显示的下一个单元格的信息,但是这个单元格的准备工作完全由您负责在重复使用它之前。

为此,您必须在-(void)prepareForReuse中实施RecruimentListItemCell,在那里您必须确保所有需要在单元格中重新填充的项目都被正确重置,以便在单元格中可以适当地重新填充。

例如,如果在RecruimentListItemCell中您要添加标签&#34; SampleLable&#34;作为子视图,但在[SampleLable removeFromSuperView]中没有-(void)prepareForReuse,然后每次重复使用单元格时,&#34; SampleLable&#34;将会一次又一次地添加到它中,最终你会注意到事情看起来不应该像你的#34;重复创建标签&#34;

这就是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。 当下一个单元格出现时,如果它需要图标,它只是取消隐藏它们,如果需要标签,则添加它们。

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

答案 1 :(得分:1)

您可以将这三个标签设为using clock = std::chrono::system_clock; using dsec = std::chrono::duration<double>; using tps = std::chrono::time_point<clock, dsec>; tps tp = clock::now(); 的属性,并使用延迟加载对其进行初始化。

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; } 中为这些标签设置setText。

setEntity:

为了进行精细重用,您可以覆盖选择器-(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

答案 2 :(得分:0)

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

答案 3 :(得分:-1)

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

static NSString *recruitmentTableIdentifier = @"RecruimentListItemCell";

RecruimentListItemCell *cell = [tableView dequeueReusableCellWithIdentifier:recruitmentTableIdentifier];

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

希望,它会起作用。
感谢。