ios - TableView Cell 自定义类型 Text 自身重叠或为空白

标签 ios iphone uitableview core-data

希望有人可以建议我使用自定义标签填充 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];

}

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

- (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;
    }
}

下面是一些截图:

storyboard

changed cell

selected cell

最佳答案

***更新 - 当使用自定义单元格时删除原型(prototype)单元格,因为你不需要它!

我终于弄明白为什么它不起作用了。整个问题是 Prototype Cell,因为您必须设置重用标识符,并且在大多数教程中他们使用字符串“Cell”。

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

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

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

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

-(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 来计算这里的 subview 数来解决这个问题:

- (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 作为标识符。在 Storyboard 中,我仍然有原型(prototype)单元格的“单元格”标识符。如果你里面没有东西,它就会提示。这是我的最终代码:

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

使用以下代码在核心数据对象更改时更新标签文本:

- (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;
  }
}

我还发现,有时当返回到 TableView 时,表并不总是更新,因此要解决此问题,您可以使用:

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

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

关于ios - TableView Cell 自定义类型 Text 自身重叠或为空白,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18588441/

相关文章:

android - SQLite TEXT 比较不适用于附加的数据库

objective-c - 具有分组样式的矩形角的 UITableViewCell

ios - 带有 appendPartWithFileData 的多个文件

ios - SKProductsRequestDelegate 永远不会被调用

iphone - 使用 AVAudioPlayer 快进歌曲

javascript - 悬停链接需要双击

iphone - 具有大 uint8_t[ ] 数组的 iOS 问题

iphone - UITableView - 如何左对齐?

ios - uiTableView 选择上一个选定的行?

ios - 如何在触发 UITableViewRowAction 时显示图像?