Приложение падает при удалении из UITableView из-за соединения с собственной ссылкой - PullRequest
3 голосов
/ 20 октября 2010

Я новичок в разработке для iPhone (и первый вопрос опубликован здесь) и застрял с основными данными и представлениями таблиц.

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

Вот описание модели данных:

Существует два объекта; Персона и Соединение .

Персона содержит имя (строка), соединения (ко многим отношениям к соединение -> источник , правило каскадного удаления) и connectedby (Отношение ко многим Соединение -> Соединение , правило каскадного удаления)

Соединение содержит отношение (строка), источник (отношение к персона -> соединения , исключить правило удаления) и соединение (отношение к Person -> connectedby , аннулировать правило удаления)

Идея состоит в том, что есть два человека, связанных отношениями (например, Мать или Сын )

В моем TableViewController я реализую следующее:

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

и

- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath {
    UITableView *tableView = self.tableView;
    Person *person = nil;
    switch(type) {
    case NSFetchedResultsChangeInsert:
        [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];         
        break;
    case NSFetchedResultsChangeDelete:
        [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
        break;
    case NSFetchedResultsChangeUpdate:
        person = (Person *)[fetchedResultsController objectAtIndexPath:indexPath];
        [self configureCell:(PersonTableViewCell *)[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
        break;          
    case NSFetchedResultsChangeMove:
        person = (Person *)[fetchedResultsController objectAtIndexPath:indexPath];
        [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
        [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
        break;
    } 
}

и

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

Здесьпримеры записей, которые я создал для тестирования этого:

Person *person1 = [NSEntityDescription insertNewObjectForEntityForName:@"Person" inManagedObjectContext:self.managedObjectContext];
[person1 setName:[NSString stringWithFormat: @"Tommy"]];

Person *person2 = [NSEntityDescription insertNewObjectForEntityForName:@"Person" inManagedObjectContext:self.managedObjectContext];
[person2 setName:[NSString stringWithFormat: @"Jane"]];

Connection *connection = [NSEntityDescription insertNewObjectForEntityForName:@"Connection" inManagedObjectContext:managedObjectContext];
[connection setConnection:person2];
[connection setSource:person1];
[connection setRelationship:[NSString stringWithFormat:@"Mother"]];

Connection *connection2 = [NSEntityDescription insertNewObjectForEntityForName:@"Connection" inManagedObjectContext:managedObjectContext];
[connection2 setConnection:person1];
[connection2 setSource:person2];
[connection2 setRelationship:[NSString stringWithFormat:@"Son"]];

Когда я удаляю запись в indexPath [0,0], т.е. Джейн в этом примере, так как представление отсортировано по имени, я генерирую следующую ошибку:

2010-10-19 16:09:01.461 HelpMe[6324:207] 
Serious application error.  
Exception was caught during Core Data change processing.  
This is usually a bug within an observer of NSManagedObjectContextObjectsDidChangeNotification.
*** -[NSMutableArray objectAtIndex:]: index 1 beyond bounds [0 .. 0] with userInfo (null)
Detected an attempt to call a symbol in system libraries that is not present on the iPhone:
_Unwind_Resume called from function -[NSManagedObjectContext(_NSInternalChangeProcessing) _processRecentChanges:] in image CoreData.

Кажется, что удаление правильно генерирует NSFetchedResultsChangeDelete для indexPath [0,0], но также сразу генерирует NSFetchedResultsChangeUpdate для [0,1], который больше не существует, так как [0,1], по-видимому, теперь в [0,0] после удаления.

Без соответствующей записи Connection удаляется нормально.

Казалось бы, я могу обойти эту проблему, просто вызвав [self.tableView reloadData] для controllerDidChangeContentвместо реализации обновлений start / end и didChangeOnject: но я не верю, что это правильный способ справиться с этим.

Я ценю любую помощь, которую кто-либо может предложить.

Ответы [ 2 ]

2 голосов
/ 26 января 2011

Я решил похожую проблему, предоставив ненулевой sectionNameKeyPath до NSFetchedResultsController initWithFetchRequest ).

Затем я избегал разделов, используя:

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
    return @"";
}

Очень раздражает.

К вашему сведению, моя проблема была в этой ошибке:

Серьезная ошибка приложения. исключение было получено от делегата NSFetchedResultsController во время вызовите -controllerDidChangeContent :. * - [NSMutableArray objectAtIndex:]: индекс 0 вне границ для пустого массива with userInfo (null)

0 голосов
/ 15 октября 2011

Вверху - (void)controller:(NSFetchedResultsController *)controller didChangeObject: я выбирал сущность из fetchedResultsController. Ну, это действительно портит вещи, когда вы только что удалили объект и должны обновить таблицу. Я переместил выборку сущности в часть NSFetchedResultsChangeUpdate. Это тогда препятствовало тому, чтобы я потерпел крах.

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