Taz*_*NZL 2 iphone core-data uitableview ios
希望有人可以告诉我正确的方法来填充UITableViewCell自定义标签.我一直遇到同样的问题,标签是空白的,或者表格填满cells重复使用的表格显示重叠label文本.
我已经按照这里为其他人提供的建议,但每次我做的事情都会中断.
**更新**
我已将代码更改为以下并且大部分工作都有效,除非我选择一个标签重叠的单元格,如下面的屏幕截图所示.我正在使用的教程的代码可以在这里找到:https://github.com/funkyboy/Core═-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];
}
Run Code Online (Sandbox Code Playgroud)
因为我使用的原型Cell核心数据,并fetchedresultcontroller在if(!cell)永远不会被调用.我将标记更改为indexPath.row编号.如果您使用预定义cell类型,我所遵循的每个教程都可以正常工作.如果我使用自己的标签自定义它永远不会有效.我不应该使用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;
}
}
Run Code Online (Sandbox Code Playgroud)
以下是一些截图:



***更新 - 使用自定义单元格时,删除原型单元格,因为您不需要它!
我终于弄明白为什么它不起作用.整个问题是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];
}
Run Code Online (Sandbox Code Playgroud)
上面的块if 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;
}
Run Code Online (Sandbox Code Playgroud)
这看起来工作正常,因为它创建了标签,但是当您滚动屏幕时,您会发现标签与我的问题重叠.这是因为当一个单元格离开屏幕并返回时,cellForRowAtIndexPath会重新使用已有标签的单元格并在顶部创建另一个Label.这种情况一直持续到您在同一个单元格上重叠7,8个或更多标签为止.我通过在didSelectRowatIndex中放置一个NSlog来计算子视图的数量来解决这个问题:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSLog(@"Count is:%i", [[tableView cellForRowAtIndexPath:indexPath].contentView.subviews count]);
}
Run Code Online (Sandbox Code Playgroud)
因此,您需要做的是在if(cell == nil)中创建自定义Label,并使用else来仅设置Label的文本.这项工作的关键是每个单元必须具有唯一的重用标识符,因此当调用CellforRowatIndexPath时,它会在第一次出现时创建一个新单元.当该单元格离开屏幕并返回时,新单元格未创建,它只是重用现有单元格并更改文本而不创建另一个标签.我已经用if(cell == nil)中的另一个NSlog检查了这个,它为每个单元格触发一次,然后它不会触发,因为它重用了出队的单元格.我只是使用字符串"myCell"+ indexPath.row作为标识符.在故事板中,我仍然拥有Prototype单元格的"Cell"标识符.如果你在那里没有东西,它会抱怨.
- (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;
}
Run Code Online (Sandbox Code Playgroud)
我还在使用代码:
- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath {
FailedBankInfo *info = [_fetchedResultsController objectAtIndexPath:indexPath];
UILabel *theLabel = (UILabel *)[cell viewWithTag:101];
theLabel.text = [NSString stringWithFormat:@"%@", info.name];
}
Run Code Online (Sandbox Code Playgroud)
使用以下代码更改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;
}
}
Run Code Online (Sandbox Code Playgroud)
我也发现有时候当回到表视图时,表并不总是更新,所以为了解决这个问题你可以使用:
-(void) viewWillAppear {
[self.tableView reloadData];
}
Run Code Online (Sandbox Code Playgroud)
感谢您的所有输入,它帮助我找到了解决方案,我希望这可以帮助其他遇到同样问题的人.我想我已经解释得很好了.我无论如何都不是专家.只是另一个人试图建立一个应用程序:)
我只用2-3行代码修复它.发生这种情况是因为tableView使用此方法显示您的内容.
[cell.contentView addSubView:myView];
Run Code Online (Sandbox Code Playgroud)
现在它将完美地工作如果你的tableView不是滚动但是当你滚动你的TableView然后它重叠内容,因为它不会从内存中清除旧内容,你可以在内存调试会话中看到内存使用.现在你的内存消耗将随着滚动而增加.
因此,最佳解决方案是在将新内容添加到单元格内存之前,从Cell的contentView First中清除所有旧内容.这样它将顺利运行.
在将任何内容添加到contentView之前,我使用了以下代码来清除Cell的contentView中的旧内存.
for (id object in cell.contentView.subviews)
{
[object removeFromSuperview];
}
Run Code Online (Sandbox Code Playgroud)
我认为这是完美的解决方案.但我仍然需要你的评论.请分享您的经验.
| 归档时间: |
|
| 查看次数: |
4805 次 |
| 最近记录: |