2010-08-13 2 views
4

я UITableViewController подклассы и реализованы следующиеОбновление UITableView вызовет исключение

  1. NSFetchedResultsController со своими делегатами
  2. tableView:sectionForSectionIndexTitle:atIndex:
  3. tableView:titleForHeaderInSection:

controller:didChangeObject:atIndexPath:forChangeType:newIndexPath: В

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

В модели данных для данного объекта у меня есть переходное свойство uppercaseFirstLetterOfName, которое вернет первую букву постоянного свойства.

Это все, что нужно для создания алфавитных разделов для табличных элементов и бокового индекса.

Теперь, если у меня есть одна запись для раздела, то я переименую его, чтобы он изменил раздел, я получаю следующее исключение, которое происходит где-то после NSFetchedResultsChangeMove.

*** отказ Assertion в - [UITableView _endCellAnimationsWithContext:], /SourceCache/UIKit_Sim/UIKit-984.38/UITableView.m:774

Exception был пойман во время обработки изменения ядра данных: Invalid обновление: неверное число строк в секции 0. число строк, содержащихся в существующей секции после обновления (1) должно быть равно числу строк , содержащейся в этом разделе перед обновлением (1), плюс или минус число вставленных строк или dele ted из этого раздела (вставлено 0, 1 удалено).

Любые идеи?

UPD еще немного кода:

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 
{ 
    NSInteger count = [[fetchedResultsController sections] count]; 
    return count; 
} 

- (NSInteger)tableView:(UITableView *)tableView 
         numberOfRowsInSection:(NSInteger)section 
{ 
    NSInteger numberOfRows = 0; 
    if ([[fetchedResultsController sections] count] > 0) 
    { 
     id <NSFetchedResultsSectionInfo> sectionInfo = 
       [[fetchedResultsController sections] objectAtIndex:section]; 
     numberOfRows = [sectionInfo numberOfObjects]; 
    } 
    return numberOfRows; 
} 

...

NSSortDescriptor* sortByWordDescriptor = [[NSSortDescriptor alloc] 
         initWithKey:@"subject" ascending:YES]; 
    NSArray* sortArray = [[NSArray alloc] 
         initWithObjects:sortByWordDescriptor, nil]; 
    [fetchRequest setSortDescriptors:sortArray]; 

    NSFetchedResultsController* controller = [[NSFetchedResultsController alloc] 
         initWithFetchRequest:fetchRequest 
         managedObjectContext:managedObjectContext 
         sectionNameKeyPath:@"uppercaseFirstLetterOfName" 
         cacheName:@"Root"]; 

UPD (заплата): На данный момент я исправлен код вроде этого:

case NSFetchedResultsChangeMove: 
     NSUInteger tableSectionCount = [self.tableView numberOfSections]; 
     NSUInteger modelSectionCount = [[controller sections] count]; 
     if (modelSectionCount > tableSectionCount) 
     { 
      [self.tableView insertSections:[NSIndexSet 
           indexSetWithIndex:[newIndexPath section]] 
           withRowAnimation:UITableViewRowAnimationNone]; 
     } 
     else if(modelSectionCount < tableSectionCount) 
     { 
      if (tableSectionCount > 1) 
      { 
       [self.tableView deleteSections:[NSIndexSet 
           indexSetWithIndex:[indexPath section]] 
           withRowAnimation:UITableViewRowAnimationNone]; 
      } 
     } 
     [tableView deleteRowsAtIndexPaths:[NSArray 
           arrayWithObject:indexPath] 
           withRowAnimation:UITableViewRowAnimationFade]; 
     [tableView insertRowsAtIndexPaths:[NSArray 
           arrayWithObject:newIndexPath] 
           withRowAnimation:UITableViewRowAnimationFade]; 

     break; 

Так далеко не крушение, но это правильное решение?

+0

Я думаю, 'NSFetchedResultsController' не знает, что раздел будет удален, так как' контроллера: didChangeSection: ... ' никогда не стреляет. Но как справиться с этим? – Pablo

+1

Согласно следам, после изменения объекта и, как результат, количество секций должно быть уменьшено, на самом деле '[[fetchedResultsController sections] count]' возвращает старое значение. Итак, как обновить количество разделов контроллера или аннулировать свойство переходного процесса? – Pablo

ответ

0

Код, обрабатывающий разделы, будет ожидать, что элемент будет иметь определенный индекс, но этот элемент больше не существует, и, похоже, вы не закодированы для этого сценария, возвращая нуль, когда там нет элемента.

+0

Не могли бы вы быть более конкретными? Какой код будет ожидать, мой или каркас? Где я должен возвращать нуль? – Pablo

0

вы должны изменить массив данных, прежде чем использовать какой-либо метод insert или delete таблицыView!

[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] 
     withRowAnimation:UITableViewRowAnimationFade]; 
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] 
     withRowAnimation:UITableViewRowAnimationFade]; 

и NSFetchedResultsChangeMove должны завершить действие вашего пользовательского интерфейса. , так что вам нужно сделать это, чтобы изменить порядок элементов datasorce.

+0

проверить демо демо-коды здесь: http://github.com/erica/iphone-3.0-cookbook-/blob/master/C11-Tables/13-Enabling%20Reordering/main.m – xhan

+0

Изменить порядок элементов данных? Я не уверен, понимаю ли я, как бы это сделать. В этом контроллере я просто передаю объект из 'fetchedResultsController' в другой контроллер представления, где он изменен и в это время уволены делегаты из NSFetchedResultsController. Демонстрационные коды не используют 'NSFetchedResultsController', поэтому я не могу понять ... – Pablo

+0

На самом деле, используя' NSFetchedResultsController', сначала производят модификации datasource, а затем вызывает 'didChangeObject' для обновления таблицы данных. Все еще запутано и ищет решение. – Pablo

2

Я думаю, что знаю, что с тобой происходит.Убедитесь, что у вас есть:

- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller { 
    [self.tableView beginUpdates]; 
} 

- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller { 
    [self.tableView endUpdates]; 
} 

В документации говорится о методе «beginUpdates»:

вызова этот метод, если вы хотите, последующие вставки, удаления и операции выбора (например, cellForRowAtIndexPath: и indexPathsForVisibleRows) для анимации одновременно.

что то, что вы делаете с:

[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; 
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade]; 

Приветствиях

Смежные вопросы