希望有人可以建议我使用自定义标签填充 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;
}
}
下面是一些截图:
最佳答案
***更新 - 当使用自定义单元格时删除原型(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/