UITableViewCell 在编辑模式下移动时显示两个不同的项目
Posted
技术标签:
【中文标题】UITableViewCell 在编辑模式下移动时显示两个不同的项目【英文标题】:UITableViewCell showing two different items while I move it in edit mode 【发布时间】:2011-05-29 19:53:34 【问题描述】:我有一个由 Core Data 支持的基本“待办事项列表”iPhone 应用程序。我在实现允许用户选择排序顺序(Alpha、创建日期、自定义)的系统时遇到问题。如果他们选择自定义,那么他们可以通过编辑模式手动移动项目。
现在,表格显示和核心数据正确反映了排序选择。但是,如果我执行以下操作,则会出现如下屏幕截图所示的奇怪情况。
导致问题:
-
启动应用程序并更改排序 - 比如从更改日期到 Alpha
更改为自定义排序
尝试在编辑模式下移动项目(错误仅在我按住并拖动项目时出现)
截图:
当排序首选项改变时,我实际上是在杀死我的 NSManagedResultsFetcher,用新的排序描述符创建一个新的并重新加载表
- (void)startFetcher
BOOL success;
NSError * error;
NSFetchRequest * fetchRequest;
NSSortDescriptor * sortDescriptor;
OurListsAppDelegate* delegate;
delegate = [[UIApplication sharedApplication] delegate];
assert([ListMaster sharedListMaster] != nil);
assert([ListMaster sharedListMaster].managedObjectContext != nil);
NSPredicate *predicate = [NSPredicate predicateWithFormat:
@"(parentCreatedUdid = %@) AND (parentCreatedDate = %@)", self.parentCreatedUdid, self.parentCreatedDate];
if (self.parentItem != nil)
sortDescriptor = [[[NSSortDescriptor alloc] initWithKey:self.parentItem.sortPreference ascending:YES] autorelease];
else
sortDescriptor = [[[NSSortDescriptor alloc] initWithKey:delegate.rootSortPreference ascending:YES] autorelease];
assert(sortDescriptor != nil);
fetchRequest = [[[NSFetchRequest alloc] init] autorelease];
assert(fetchRequest != nil);
[fetchRequest setPredicate:predicate];
[fetchRequest setEntity:[ListMaster sharedListMaster].listEntity];
[fetchRequest setFetchBatchSize:20];
[fetchRequest setSortDescriptors:[NSArray arrayWithObject:sortDescriptor]];
assert(self.fetcher == nil);
self.fetcher = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:[ListMaster sharedListMaster].managedObjectContext sectionNameKeyPath:nil cacheName:nil];
assert(self.fetcher != nil);
self.fetcher.delegate = self;
success = [self.fetcher performFetch:&error];
if ( ! success )
[[QLog log] logWithFormat:@"viewer fetch failed %@", error];
以及当排序顺序改变时调用的方法
- (void)restartFetcher
[_fetcher release];
self.fetcher = nil;
[self startFetcher];
[self reloadTable];
编辑:根据请求在下面添加代码
- (UITableViewCell *)tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)indexPath
UITableViewCell * result;
assert(tv == self.tableView);
assert(indexPath != NULL);
if ( [self hasNoItems] )
// There are no items to display; return a cell that simple says "No items".
result = [self.tableView dequeueReusableCellWithIdentifier:@"cell"];
if (result == nil)
result = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cell"] autorelease];
assert(result != nil);
result.textLabel.text = @"No items";
result.textLabel.textColor = [UIColor darkGrayColor];
result.textLabel.textAlignment = UITextAlignmentCenter;
result.selectionStyle = UITableViewCellSelectionStyleNone;
else
ListItem * item;
item = [self.fetcher objectAtIndexPath:indexPath];
assert([item isKindOfClass:[ListItem class]]);
UITableViewCell *cell = [tv dequeueReusableCellWithIdentifier:@"cell"];
if (cell == nil)
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cell"] autorelease];
assert(cell != nil);
assert(cell.selectionStyle == UITableViewCellSelectionStyleBlue);;
ToggleImageControl *toggleControl = [[ToggleImageControl alloc] initWithFrame: CGRectMake(4, 6, 32, 32) status:item.isDone];
toggleControl.tag = indexPath.row;
[cell.contentView addSubview: toggleControl];
[toggleControl release];
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(50, 0, 260, 44)];
label.text = item.name;
label.textAlignment = UITextAlignmentLeft;
[cell.contentView addSubview:label];
[label release];
if ([item.isList boolValue] == YES)
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
else
cell.accessoryType = UITableViewCellAccessoryNone;
result = cell;
return result;
【问题讨论】:
你能发布你的tableView:cellForRowAtIndexPath:
吗?
按要求发布了 tableView:cellForRowAtIndexPath。谢谢你看看这个。我是 iPhone 开发的新手,所以如果有人有需要看的东西的指针(但不是事实上的解决方案),它也会有所帮助。
【参考方案1】:
你的问题出在这几行,
ToggleImageControl *toggleControl = [[ToggleImageControl alloc] initWithFrame: CGRectMake(4, 6, 32, 32) status:item.isDone];
toggleControl.tag = indexPath.row;
[cell.contentView addSubview: toggleControl];
[toggleControl release];
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(50, 0, 260, 44)];
label.text = item.name;
label.textAlignment = UITextAlignmentLeft;
[cell.contentView addSubview:label];
[label release];
这是单元重用的问题。每次配置可重用单元之前,都需要对其进行重置。在这种情况下,当我注意到一个单元格的内容与另一个单元格的内容合并时,我意识到这就是问题所在。当这种事情发生时,通常就是问题所在。您做错的是,每次重用单元格时,您都在添加您在上面创建的两个对象。在切换控件的情况下,它们会重叠,您不会注意到,但文本会发生变化并且重叠突出。
你能做什么?
您可以搜索这两个对象并将它们从单元格中删除,然后执行上述操作,或者您可以创建UITableViewCell
的自定义子类并添加两个retain
ed 属性——一个用于切换控件和一个用于标签,稍后执行此操作,
ToggleImageControl *toggleControl = [[ToggleImageControl alloc] initWithFrame: CGRectMake(4, 6, 32, 32) status:item.isDone];
toggleControl.tag = indexPath.row;
cell.toggleControl = toggleControl;
[toggleControl release];
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(50, 0, 260, 44)];
label.text = item.name;
label.textAlignment = UITextAlignmentLeft;
cell.label = label;
[label release];
【讨论】:
效果很好。我找错地方了,所以这很有帮助。以上是关于UITableViewCell 在编辑模式下移动时显示两个不同的项目的主要内容,如果未能解决你的问题,请参考以下文章
使用 Interface Builder 编辑 UITableViewCell 的模式
在编辑模式下重新排序时更改 UITableViewCell 的背景颜色
动画 UITableViewCell ContentView 在进入编辑模式时淡出
深挖UITableViewCell-编辑多选模式下,引发的深思