【问题标题】:TableView Cell Custom type Text Overlaps itself or is BlankTableView 单元格自定义类型文本自身重叠或为空白
【发布时间】:2013-09-03 09:17:14
【问题描述】:

希望有人可以建议我使用自定义标签填充UITableViewCell 的正确方法。我一直遇到同样的问题,要么标签是空白的,要么当表格填满 cells 重复使用的标签时显示重叠的 label 文本。

我遵循了这里为其他人提供的建议,但每次我这样做都会有问题。

** 更新**

我已将代码更改为以下代码,并且大部分代码都可以正常工作,除非我选择一个单元格时标签重叠,如下面的屏幕截图所示。我正在使用的教程的代码可以在这里找到:https://github.com/funkyboy/Core-Data-on-iOS-5-Tutorial--How-To-Work-with-Relations-and-Predicates

这是我的代码:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

if (!cell) {
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}

FailedBankInfo *info = [_fetchedResultsController objectAtIndexPath:indexPath];

CGRect infoFrame = CGRectMake(10, 10, 200, 16);
UILabel *infoLabel = [[UILabel alloc] initWithFrame:infoFrame];
infoLabel.textColor = [UIColor blackColor];
infoLabel.backgroundColor = [UIColor yellowColor];
infoLabel.font = [UIFont systemFontOfSize:12];
infoLabel.textAlignment = NSTextAlignmentCenter;
infoLabel.tag = indexPath.row;
infoLabel.text = [NSString stringWithFormat:@"%@, %@", info.city, info.state];
[cell addSubview:infoLabel];

return cell;
}

- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath {

FailedBankInfo *info = [_fetchedResultsController objectAtIndexPath:indexPath];
UILabel *theLabel = (UILabel *)[cell.contentView viewWithTag:indexPath.row];
theLabel.text = [NSString stringWithFormat:@"%@, %@",
                 info.city, info.state];

}

因为我将原型Cell 与Core Data 一起使用,而fetchedresultcontroller 永远不会调用if(!cell)。我将标签更改为 indexPath.row 编号。如果您使用预定义的 cell 类型,我遵循的每个教程都可以正常工作。如果我将自定义与我自己的标签一起使用,它永远不会奏效。我不应该对 tableview 数据使用 fetchedresultscontroller 吗?如果我在详细视图中更改城市标题并将其保存,则会调用以下代码:

- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath {

UITableView *tableView = self.tableView;

switch(type) {

    case NSFetchedResultsChangeInsert:
        [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
        break;

    case NSFetchedResultsChangeDelete:
        [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
        break;

    case NSFetchedResultsChangeUpdate:
        [self configureCell:[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
        break;

    case NSFetchedResultsChangeMove:
        [tableView deleteRowsAtIndexPaths:[NSArray
                                           arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
        [tableView insertRowsAtIndexPaths:[NSArray
                                           arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
        break;
    }
}

以下是一些截图:

【问题讨论】:

  • 你试过我的解决方案了吗?如果是并且有效,请将其标记为已接受:)
  • @MongiZaidi 是的,我做了 Mongi,但标签根本不显示。

标签: ios iphone uitableview core-data


【解决方案1】:

***更新 - 使用自定义单元格时,删除不需要的原型单元格!!

我终于知道为什么它不起作用了。整个问题在于原型单元,因为您必须设置一个重用标识符,并且在大多数教程中他们使用字符串“Cell”。

当 tableview 加载时,它已经有一个带有标识符“Cell”的单元格,因此它不会创建新单元格,它只是重用具有标识符“Cell”的单元格。

static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

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

上面的 if (cell == nil) 块永远不会被调用,因为它正在重用已经存在的 Prototype 单元格。另一个问题是在此块下方创建标签,如下所示:

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

if (!cell) {
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
FailedBankInfo *info = [_fetchedResultsController objectAtIndex:indexPath.row];

CGRect infoFrame = CGRectMake(10, 10, 200, 16);
UILabel *infoLabel = [[UILabel alloc] initWithFrame:infoFrame];
infoLabel.textColor = [UIColor blackColor];
infoLabel.backgroundColor = [UIColor yellowColor];
infoLabel.font = [UIFont systemFontOfSize:12];
infoLabel.textAlignment = NSTextAlignmentCenter;
infoLabel.tag = 101;
infoLable.text = [NSString stringWithFormat:@"%@, %@",
         info.city, info.state];
[cell.contentView addSubview:infoLabel];

return cell;
}

这似乎工作正常,因为它确实创建了标签,但是当您滚动屏幕时,您会发现标签与我的问题一样重叠。这是因为当一个单元格离开屏幕并返回到 cellForRowAtIndexPath 时,它会重用一个已经有标签的单元格并在顶部创建另一个标签。这种情况会一直发生,直到您有 7、8 个或更多标签重叠在同一个单元格上。我通过在 didSelectRowatIndex 中放置一个 NSlog 来计算这里的子视图数量来解决这个问题:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {

NSLog(@"Count is:%i", [[tableView cellForRowAtIndexPath:indexPath].contentView.subviews count]);
}

所以您需要做的是在 if (cell == nil) 中创建自定义标签,并使用 else 仅设置标签的文本。这样做的关键是每个单元格必须有一个唯一的重用标识符,因此当调用 CellforRowatIndexPath 时,它会在第一次出现时创建一个新单元格。当该单元格离开屏幕并返回未创建新单元格时,它只是重用现有单元格并更改文本而不创建另一个标签。我已经用 if (cell == nil) 中的另一个 NSlog 检查了这一点,它为每个单元格触发一次,之后它不会触发,因为它重用了出队的单元格。我只是使用字符串“myCell”+ indexPath.row 作为标识符。在情节提要中,我仍然有原型单元格的“单元格”标识符。如果你那里没有东西,它会抱怨。这是我的最终代码:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *myCellID = [NSString stringWithFormat:@"myCell%i", indexPath.row];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:myCellID];

FailedBankInfo *info = [_fetchedResultsController objectAtIndexPath:indexPath];

if (cell == nil) {
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:myCellID];
    CGRect infoFrame = CGRectMake(10, 10, 200, 16);
    UILabel *infoLabel = [[UILabel alloc] initWithFrame:infoFrame];
    infoLabel.textColor = [UIColor blackColor];
    infoLabel.backgroundColor = [UIColor yellowColor];
    infoLabel.font = [UIFont systemFontOfSize:12];
    infoLabel.textAlignment = NSTextAlignmentCenter;
    infoLabel.tag = 101;
    infoLabel.text = [NSString stringWithFormat:@"%@", info.name];
    [cell.contentView addSubview:infoLabel];
}
else {
    UILabel *theLabel = (UILabel *)[cell viewWithTag:101];
    theLabel.text = [NSString stringWithFormat:@"%@", info.name];
}

return cell;
}

另外我还在使用代码:

- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath {

FailedBankInfo *info = [_fetchedResultsController objectAtIndexPath:indexPath];
UILabel *theLabel = (UILabel *)[cell viewWithTag:101];
theLabel.text = [NSString stringWithFormat:@"%@", info.name];
}

Core 数据对象发生变化时更新标签文本,代码如下:

- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath {

UITableView *tableView = self.tableView;

switch(type) {

    case NSFetchedResultsChangeInsert:
        [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
        break;

    case NSFetchedResultsChangeDelete:
        [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
        break;

    case NSFetchedResultsChangeUpdate:
        [self configureCell:[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
        break;

    case NSFetchedResultsChangeMove:
        [tableView deleteRowsAtIndexPaths:[NSArray
                                           arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
        [tableView insertRowsAtIndexPaths:[NSArray
                                           arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
        break;
  }
}

我还发现有时在返回表格视图时表格并不总是更新,因此您可以使用以下方法来解决此问题:

-(void) viewWillAppear {
[self.tableView reloadData];
}

感谢您的所有意见,它确实帮助我找到了解决方案,我希望这对遇到同样问题的其他人有所帮助。我想我已经解释得很好了。我无论如何都不是专家。只是另一个试图构建应用程序的人:)

【讨论】:

    【解决方案2】:

    我只是用 2-3 行代码修复了它。发生这种情况是因为当 tableView 使用 this 显示您的内容时。

    [cell.contentView addSubView:myView];
    

    现在,如果您的 tableView 没有滚动,它将完美运行,但是当您滚动 TableView 时,它会与内容重叠,因为它不会从内存中清除旧内容,您可以在内存调试会话中查看内存使用情况。现在你的内存消耗会随着滚动而增加。

    所以最好的解决方案是先从 Cell 的 contentView 中清除所有旧内容,然后再将新内容添加到 Cell Memory。这样它才能顺利运行。

    在将任何内容添加到 contentView 之前,我已使用以下代码从 Cell 的 contentView 中清除旧内存。

    for (id object in cell.contentView.subviews)
    {
        [object removeFromSuperview];
    }  
    

    我认为这是完美的解决方案。但我仍然需要你们的评论。请分享您的经验。

    【讨论】:

      【解决方案3】:

      为情节提要创建自定义单元格类,如下所示。直观地设置标签并设置所需的属性,如颜色、字体、大小等

      myCell.h
      
      #import <UIKit/UIKit.h>
      
      @interface myCell : UITableViewCell
      
      //connect your labels and image as below
      
      @property (weak, nonatomic) IBOutlet UIImageView *myImage;
      @property (weak, nonatomic) IBOutlet UILabel *myLabel1;
      @property (weak, nonatomic) IBOutlet UILabel *myLabel2;
      @property (weak, nonatomic) IBOutlet UILabel *myLabel3;
      
      @end
      
      
      yourViewController.m
      
      //Set up your custom cell
      
      -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
      
      static NSString *cellIdentifier = @"Cell";
      myCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
      
      if (cell == nil) {
      
          cell = [[myCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
      
      }
      
      cell.myLabel1.text = @"hello1";
      cell.myLabel2.text = @"hello2";
      cell.myLabel3.text = @"hello3";
      
      [cell.myImage setImage:[UIImage imageNamed:@"google.jpg"]];
      return cell;
      
      }
      

      【讨论】:

        【解决方案4】:
        -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
        {
            static NSString *CellIdentifier = @"Cell";
            UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
        
        if (!cell) {
            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
            }
            FailedBankInfo *info = [_fetchedResultsController objectAtIndex:indexPath.row];
        
            CGRect infoFrame = CGRectMake(10, 10, 200, 16);
            UILabel *infoLabel = [[UILabel alloc] initWithFrame:infoFrame];
            infoLabel.textColor = [UIColor blackColor];
            infoLabel.backgroundColor = [UIColor yellowColor];
            infoLabel.font = [UIFont systemFontOfSize:12];
            infoLabel.textAlignment = NSTextAlignmentCenter;
            infoLabel.tag = 101;
            infoLable.text = [NSString stringWithFormat:@"%@, %@",
                     info.city, info.state];
            [cell.contentView addSubview:infoLabel];
        
            return cell;
        }
        

        【讨论】:

        • 你能看看我的回答,让我知道你的想法吗?
        【解决方案5】:

        我以前多次在使用 tableview 时遇到过这种问题。到目前为止,我发现的最佳解决方案是创建自己的“reuseTableViewCellWithIdentifier”方法(在 myViewController.m 中),然后使用它来获取“cellForRowAtIndexPath 方法”中的单元格。 在您的情况下,它将是这样的:

        -(UITableViewCell *)reuseTableViewCellWithIdentifier:(NSString *)identifier withIndexPath:(NSIndexPath *)indexPath{
        UITableViewCell *cell =[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
           FailedBankInfo *info = [_fetchedResultsController objectAtIndex:indexPath.row];
           CGRect infoFrame = CGRectMake(10, 10, 200, 16);
           UILabel *infoLabel = [[UILabel alloc] initWithFrame:infoFrame];
           infoLabel.textColor = [UIColor blackColor];
           infoLabel.backgroundColor = [UIColor yellowColor];
           infoLabel.font = [UIFont systemFontOfSize:12];
           infoLabel.textAlignment = NSTextAlignmentCenter;
           infoLabel.tag = 101;
           infoLabel.text = [NSString stringWithFormat:@"%@, %@", info.city, info.state];
           [cell.contentView addSubview:b];
           return cell;
        }
        

        现在您只需要获取带有标签的标签并在您的 cellForRow 方法中更改其值,如下所示:

          - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
        {
            static NSString *CellIdentifier = @"Cell";
            UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
            if (nil == cell) {
                cell = [self reuseTableViewCellWithIdentifier:CellIdentifier withIndexPath:indexPath];
            }
            UILabel *infoLabel = (UILabel *)[cell.contentView viewWithTag:101];
            FailedBankInfo *info = [_fetchedResultsController objectAtIndex:indexPath.row];
            infoLabel.text = [NSString stringWithFormat:@"%@, %@", info.city, info.state];
        
            return cell;
        }
        

        【讨论】:

        • if (nil == cell) 永远不会被调用。所以单元格是空白的。看看我想出的解决方案。
        【解决方案6】:

        我遇到了同样的问题。我认为这是因为我们正在重用标识符,因此单元格与其他单元格重叠。下面的代码行对我有用..

        UITableViewCell *cell =[tableView dequeueReusableCellWithIdentifier:nil];

        【讨论】:

          【解决方案7】:

          您只需在情节提要中该标签的属性部分中勾选清除图形上下文。

          【讨论】:

          • 这应该是一个评论。
          猜你喜欢
          • 1970-01-01
          • 2011-02-23
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多