Как правильно удалить строки в UITableView (контролируется NSFetchedResultsController), также используя UISearchDisplayController? - PullRequest
1 голос
/ 05 ноября 2010

В моем приложении для iPhone у меня есть (не сгруппированный) UITableView, который использует все «навороты», включая (a) NSFetchedResultsController для его обновления, (b) несколько разделов, (c) возможность добавитьи удалите элементы, и (d) UISearchDisplayController, чтобы позволить пользователю выполнять поиск в списке, который может быть очень длинным.

У меня возникают проблемы, когда пользователь пытается удалить элементы, когда они находятся впроцесс поиска.Я получаю эту ошибку: Serious application error. An exception was caught from the delegate of NSFetchedResultsController during a call to -controllerDidChangeContent:. Invalid update: invalid number of sections. The number of sections contained in the table view after the update (1) must be equal to the number of sections contained in the table view before the update (21), plus or minus the number of sections inserted or deleted (0 inserted, 0 deleted). with userInfo (null)

Кажется, что проблема возникает из-за того, что, когда приложение переключается в режим поиска, вместо обычного количества разделов (которые алфавитные, AZ), оно переключаетсяв один раздел («Результаты поиска»).Поэтому, когда он пытается удалить элемент, он думает, что правильное количество разделов - это большее число, когда оно просто в одном разделе (Результаты поиска).

Вот мой код для управления извлеченными результатамиконтроллер. Знаете ли вы, как правильно обращаться с этим типом действия?

- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
// if (!self.searchDisplayController.isActive) {
  [self.tableView beginUpdates];
// }
}


- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo
           atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type {

    switch(type) {
        case NSFetchedResultsChangeInsert:
            [self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
            break;

        case NSFetchedResultsChangeDelete:
            [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
            break;
    }
}


- (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:
   if (!self.searchDisplayController.isActive) {
    [tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
   } else {
   // I currently don't do anything if the search display controller is active, because it is throwing similar errors.
   }
   break;

        case NSFetchedResultsChangeMove:
            [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
            [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]withRowAnimation:UITableViewRowAnimationFade];
            break;
    }
}


- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
// if (!self.searchDisplayController.isActive) {
  [self.tableView endUpdates];
// }
}

1 Ответ

1 голос
/ 07 декабря 2010

Если у вас есть NSFetchedResultsController, почему бы вам просто не создать предикат и не установить его на контроллере в качестве фильтра?

Примерно так:

NSPredicate *predicate =[NSPredicate predicateWithFormat:@"name contains[cd] %@", searchText];
[fetchedResultsController.fetchRequest setPredicate:predicate];

NSError *error = nil;
if (![[self fetchedResultsController] performFetch:&error]) {
        // Handle error
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        // Fail
}           

[self.tableView reloadData];
...