TableView单元格自定义types文本自身重叠或为空白

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

我遵循了在这里为别人所build议的事情,但是每一次我都做了一些rest。

**更新**

我已经将代码更改为下面的代码,除了当我select一个单元格时标签重叠,如下面的屏幕截图所示。 我正在使用的教程代码可以在这里find: 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]; } 

因为我正在使用具有核心数据的原型Cellfetchedresultcontroller ,所以不会调用if(!cell) 。 我将标记更改为indexPath.row数字。 如果使用预定义的celltypes,我所遵循的每个教程都可以正常工作 如果我用我自己的标签自定义它永远不会工作。 我应该不使用fetchedresultscontroller的tableview数据? 如果我在详细视图中更改城市标题并保存,则会调用以下代码:

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

以下是一些截图:

故事板

改变了细胞

选中单元格

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

我终于明白了为什么它不起作用。 整个问题是原型单元,因为你必须设置一个重用的标识符,并在大多数教程中使用string“单元”。

当tableview加载它已经有一个单元格与标识符“单元”,所以它不会创build一个新的单元格,它只是重用具有标识符“单元格”的单元格。

 static NSString *CellIdentifier = @"Cell"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; } 

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

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

这看起来工作正常,因为它创build的标签,但当你滚动屏幕上,你发现标签重叠自己在我的问题。 这是因为当一个单元格离开屏幕,并返回cellForRowAtIndexPath重用已经有一个标签的单元格,并在顶部创build另一个标签。 这种情况会持续发生,直到您在同一个单元格上重叠了7个,8个或更多个标签。 我通过在didSelectRowatIndex中放置一个NSlog来计算子视图的数量:

 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { NSLog(@"Count is:%i", [[tableView cellForRowAtIndexPath:indexPath].contentView.subviews count]); } 

所以你需要做的是在if(cell == nil)中创build自定义Label,并使用else来设置Label的文本。 这个工作的关键是每个单元必须有一个唯一的重用标识符,所以当调用CellforRowatIndexPath时,它会在第一次出现时创build一个新的单元。 当这个单元格离开屏幕,并返回一个新的单元格不创build它只是重用现有的和改变文本,而不创build另一个标签。 我已经在if(cell == nil)中检查了另一个NSlog,它为每个单元触发一次,之后它不会触发,因为它重用了出队单元。 我只是使用string“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]; } 

感谢您的所有意见,它确实帮助我find了一个解决scheme,我希望这可以帮助任何遇到同样问题的人。 我想我已经解释得很好了。 我不是任何方面的专家。 只是另一个人试图build立一个应用程序:)

我只是用2-3行代码修复它。 这是因为当tableView使用这个显示你的内容时发生的。

 [cell.contentView addSubView:myView]; 

现在,如果你的tableView不是滚动的,但是当你滚动你的TableView的时候,它会完美的工作,因为它不会清除内存中的旧内容,你可以在内存debugging会话中看到内存使用情况。 现在你的内存消耗会随着滚动而增加。

所以最好的解决scheme是在将新内容添加到单元存储器之前先清除单元格的contentView中的所有旧内容。 这样它会顺利运行。

在将content添加到contentView之前,我已经使用了以下代码来清除Cell的contentView中的旧内存。

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

我认为这是完美的解决scheme。 但是我还是需要你们的评价。 请分享你的经验。

对于故事板创build自定义单元格类如下。可视化设置您的标签,并设置所需的属性,如颜色,字体,大小等

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

以前我多次用tableview遇到过这样的问题。 我发现迄今为止最好的解决scheme是创build我自己的“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; } 

我有同样的问题。我认为这是因为我们正在重复使用的标识符,所以细胞重叠在其他人。 下面的代码行为我工作..

UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:nil];

您只需要在故事板中的该标签的属性部分中清除graphics上下文。