我有一个由Core Data支持的基本“待办事项列表”iPhone应用程序。我在实现允许用户选择排序顺序(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;
}
答案 0 :(得分: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];