将数据分配给 UILabel 后 UITableViewCell 显示不正确的数据

Posted

技术标签:

【中文标题】将数据分配给 UILabel 后 UITableViewCell 显示不正确的数据【英文标题】:UITableViewCell displaying incorrect data after assigning data to an UILabel 【发布时间】:2016-07-19 04:08:42 【问题描述】:

我在处理UITableView 时遇到了一个有趣的问题。如果有人能指出我在哪里犯了错误,我将不胜感激。

所以,情况是:我有一个NSDictionariesNSArray,我试图让UITableView 中的每一行都显示相应的NSDictionary。下面是“cellForRowAtIndexPath”方法的代码片段:

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

    // configure custom cell
    static NSString *cellReuseId = @"cell";

    SearchTableViewCell *searchCell = [tableView dequeueReusableCellWithIdentifier:cellReuseId forIndexPath:indexPath];

    if (self.realData.count > 0) 
        self.tempDict = self.realData[indexPath.row];
        [searchCell initLabels:[self.tempDict valueForKey:@"psnname"] withDept:[self.tempDict valueForKey:@"deptname"] withPostion:[self.tempDict valueForKey:@"position"] withTel:[self.tempDict valueForKey:@"tel"] withFax:[self.tempDict valueForKey:@"fax"]];  
     else 
        NSLog(@"no data");
    
    return searchCell;

我创建了一个自定义 UITableViewCell,并尝试通过调用“initLabels...”方法在 custom UITableViewCell 中初始化五个 UILabels。下面是自定义UITableViewCellclass中的"initLabels..."方法:

-(void) initLabels:(NSString *)psn withDept:(NSString *)dept withPostion:(NSString *)pos withTel:(NSString *)tell withFax:(NSString *)faxx
    int tempWidth = self.frame.size.width/5;

    self.psnname = [[UILabel alloc] initWithFrame:CGRectMake(self.frame.origin.x + 10, self.frame.origin.y, tempWidth * 0.8, self.frame.size.height)];
    self.deptname = [[UILabel alloc] initWithFrame:CGRectMake(self.frame.origin.x + self.psnname.frame.size.width + 5, self.frame.origin.y , tempWidth * 1.1, self.frame.size.height)];
    self.position = [[UILabel alloc] initWithFrame:CGRectMake(self.deptname.frame.origin.x + self.deptname.frame.size.width + 5, self.frame.origin.y , tempWidth * 1.1, self.frame.size.height)];
    self.tel = [[UILabel alloc] initWithFrame:CGRectMake(self.position.frame.origin.x + self.position.frame.size.width + 5, self.frame.origin.y , tempWidth * 0.7, self.frame.size.height)];
    self.fax = [[UILabel alloc] initWithFrame:CGRectMake(self.frame.size.width - tempWidth * 1.1, self.frame.origin.y , tempWidth, self.frame.size.height)];

    self.psnname.text = psn;
    self.deptname.text = dept;
    self.position.text = pos;
    self.tel.text = tell;
    self.fax.text = faxx;

    [self.contentView addSubview:self.psnname];
    [self.contentView addSubview:self.deptname];
    [self.contentView addSubview:self.position];
    [self.contentView addSubview:self.tel];
    [self.contentView addSubview:self.fax];

问题是:在使用NSString's 分配UILabel's 之前初始化那些UILabels 时,布局格式正确,但显示数据不正确;而如果在设置 UILabel 的框架之前使用 NSString 进行分配,则数据正确显示,但布局格式不正确。

导致这种情况发生的潜在原因是什么??

【问题讨论】:

细胞被重复使用。想想当您在同一个单元格实例上一遍又一遍地调用 initLabels 时会发生什么。 顺便说一句 - 用 init 前缀命名非初始化方法是个坏主意。 你能贴出你的问题的截图吗? 【参考方案1】:

您应该将构建自定义表格视图单元格的视图层次结构的代码与填充数据的代码分开。

在自定义表格视图单元格的init(或其初始化程序)中,添加以下内容:

self.psnname = [[UILabel alloc] initWithFrame:CGRectMake(self.frame.origin.x + 10, self.frame.origin.y, tempWidth * 0.8, self.frame.size.height)];
self.deptname = [[UILabel alloc] initWithFrame:CGRectMake(self.frame.origin.x + self.psnname.frame.size.width + 5, self.frame.origin.y , tempWidth * 1.1, self.frame.size.height)];
self.position = [[UILabel alloc] initWithFrame:CGRectMake(self.deptname.frame.origin.x + self.deptname.frame.size.width + 5, self.frame.origin.y , tempWidth * 1.1, self.frame.size.height)];
self.tel = [[UILabel alloc] initWithFrame:CGRectMake(self.position.frame.origin.x + self.position.frame.size.width + 5, self.frame.origin.y , tempWidth * 0.7, self.frame.size.height)];
self.fax = [[UILabel alloc] initWithFrame:CGRectMake(self.frame.size.width - tempWidth * 1.1, self.frame.origin.y , tempWidth, self.frame.size.height)];

[self.contentView addSubview:self.psnname];
[self.contentView addSubview:self.deptname];
[self.contentView addSubview:self.position];
[self.contentView addSubview:self.tel];
[self.contentView addSubview:self.fax];

然后在表格视图单元格子类中创建一个方法 - 如下所示 - 并从您的 cellForRowAtIndexPath 调用该方法

- (void)populateWithPSN:(NSString *)psn dept:(NSString *)dept postion:(NSString *)pos tel:(NSString *)tell fax:(NSString *)fax

    self.psnname.text = psn;
    self.deptname.text = dept;
    self.position.text = pos;
    self.tel.text = tell;
    self.fax.text = faxx;

【讨论】:

【参考方案2】:

另一种方法是,在自定义单元格的init方法中初始化标签并在layoutSubviews方法中设置标签的边框,该方法在单元格显示之前被多次调用,这是最好的地方设置标签的边框,例如,

在您的自定义单元格.m 文件中

-(void)layoutSubviews

   [super layoutSubviews];
   self.psnname.frame = CGRectMake(self.frame.origin.x + 10, self.frame.origin.y, tempWidth * 0.8, self.frame.size.height);
   self.deptname.frame = CGRectMake(self.frame.origin.x + self.psnname.frame.size.width + 5, self.frame.origin.y , tempWidth * 1.1, self.frame.size.height);
   self.position.frame = CGRectMake(self.deptname.frame.origin.x + self.deptname.frame.size.width + 5, self.frame.origin.y , tempWidth * 1.1, self.frame.size.height);
   self.tel.frame = CGRectMake(self.position.frame.origin.x + self.position.frame.size.width + 5, self.frame.origin.y , tempWidth * 0.7, self.frame.size.height);
   self.fax.frame = CGRectMake(self.frame.size.width - tempWidth * 1.1, self.frame.origin.y , tempWidth, self.frame.size.height);

为了设置数据,你可以使用你的方法,但为了更好的可读性,你可以像这样修改它

-(void)setLabels:(NSString *)psn withDept:(NSString *)dept withPostion:(NSString *)pos withTel:(NSString *)tell withFax:(NSString *)fax

对于细胞创建方法,

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

  // configure custom cell
  static NSString *cellReuseId = @"cell";

  SearchTableViewCell *searchCell = [tableView dequeueReusableCellWithIdentifier:cellReuseId forIndexPath:indexPath];

  if (self.realData.count > 0) 
      self.tempDict = self.realData[indexPath.row];
     [searchCell setLabels:[self.tempDict valueForKey:@"psnname"] withDept:[self.tempDict valueForKey:@"deptname"] withPostion:[self.tempDict valueForKey:@"position"] withTel:[self.tempDict valueForKey:@"tel"] withFax:[self.tempDict valueForKey:@"fax"]];  
   else 
       NSLog(@"no data");
  
  return searchCell;

【讨论】:

以上是关于将数据分配给 UILabel 后 UITableViewCell 显示不正确的数据的主要内容,如果未能解决你的问题,请参考以下文章

无法将“String”类型的值分配给“UILabel”类型

将 NSAttributedString 分配给 UILabel 很慢?

按下 UILabel 时分配变量值以打开 Apple 地图

UITableViewCell 中的 UILabel 大小不正确(分配文本后的动画)

ScrollView中的UILabel sizeToFit

将核心数据结果传递给 UILabel