Обновление UITableView вызовет исключение - PullRequest
4 голосов
/ 13 августа 2010

У меня UITableViewController подкласс и реализовано следующее

  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.

*** Ошибка подтверждения в - [UITableView _endCellAnimationsWithContext:], /SourceCache/UIKit_Sim/UIKit-984.38/UITableView.m:774

Исключение было обнаружено во время основных данных обработка изменений: неверное обновление: неверное количество строк в разделе 0. Количество строк, содержащихся в существующий раздел после обновления (1) должно быть равно количеству строк содержится в этом разделе до обновление (1), плюс или минус число из строк, вставленных или удаленных из этого раздел (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;

Пока нет сбоев, но это правильное решение?

Ответы [ 3 ]

2 голосов
/ 15 мая 2012

Мне кажется, я знаю, что с тобой происходит. Убедитесь, что у вас есть:

- (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];

Приветствия

0 голосов
/ 13 августа 2010

Вы должны изменить массив источника данных, прежде чем делать какие-либо вставки или удаления метода tableView!

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

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

0 голосов
/ 13 августа 2010

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...