У меня есть базовое приложение для iPhone «Список дел», подкрепленное Core Data.У меня проблемы с реализацией системы, которая позволяет пользователю выбирать порядок сортировки (Альфа, Дата создания, Пользовательская).Если они выбирают пользовательские, они могут перемещать элементы вручную в режиме редактирования.
В настоящий момент отображение таблицы и основные данные правильно отражают выбор сортировки.Однако, если я делаю что-то вроде следующего, я получаю странную ситуацию, как показано на скриншоте ниже.
Причины Проблема:
- Запустите приложение и измените сортировку - скажем, с даты, измененной наАльфа
- Изменить на пользовательскую сортировку
- Попробуйте переместить элемент в режиме редактирования (ошибка появляется только при удерживании и перетаскивании элемента)
Снимок экрана:

Когда изменяется предпочтение сортировки, я по сути убиваю свой 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;
}