NSFetchedResultsController делегат запускает методы только при первом запуске приложения - PullRequest
1 голос
/ 10 февраля 2012

Извините за мой ужасный английский.У меня большая проблема в моем приложении для iOS.Приложение имеет большую базу данных, которая управляется Core Data.И у меня есть много контроллеров TableView для отображения этих данных.Любые изменения в базе данных должны отображаться в виде таблицы.Это может быть достигнуто путем реализации протокола делегирования NSFetchedResultsController.Все реализации очень просты, как в книгах.Если приложение запускается в симуляторе в первый раз, и я добавляю новые записи в некоторые таблицы, успешно запускаются следующие методы делегата:

– controllerWillChangeContent:
– controller:didChangeObject:atIndexPath:forChangeType:newIndexPath:
– controllerDidChangeContent:

После остановки отладки и повторного запуска приложения ни один из перечисленных методов не запускается.Они звонят только после выполнения операции [managedObjectContext save].

Есть ли у вас какие-либо идеи, почему это происходит?

Исходный код:

//IssueProfileViewController.h class implements NSFetchedResultController delegate methods
- (NSFetchedResultsController*)fetchedResultsController{

    if (_fetchedResultsController == nil) {

        NSManagedObjectContext *managedObjectContext = self.issue.managedObjectContext;
        NSFetchRequest *aFetchRequest = [[NSFetchRequest alloc] init];
        NSEntityDescription *entity = [NSEntityDescription entityForName:@"IssueHistoryItem" inManagedObjectContext:managedObjectContext];
        [aFetchRequest setEntity:entity];

        NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"created" ascending:NO];
        NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];

        //NSPredicate *predicate = [[NSPredicate predicateWithFormat:@"issue == %@ && isComment == NO", self.issue] retain];

            NSPredicate *predicate = [NSPredicate predicateWithFormat:@"issue == %@ && isComment == NO", self.issue];

        [aFetchRequest setSortDescriptors:sortDescriptors];
        [aFetchRequest setPredicate:predicate];

            NSFetchedResultsController *aFetchedResultsController = 
                [[NSFetchedResultsController alloc] initWithFetchRequest:aFetchRequest                                                                                              
                    managedObjectContext:managedObjectContext 
                    sectionNameKeyPath:nil 
                    cacheName:nil];

        [aFetchRequest release];
        //[predicate release];
        [sortDescriptors release];
        [sortDescriptor release];
            _fetchedResultsController = aFetchedResultsController;
            _fetchedResultsController.delegate = self;
        }

        return _fetchedResultsController;
    }


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

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

-(void)controller:(NSFetchedResultsController *)controller 
  didChangeObject:(id)anObject 
      atIndexPath:(NSIndexPath *)indexPath 
    forChangeType:(NSFetchedResultsChangeType)type 
     newIndexPath:(NSIndexPath *)newIndexPath {

    NSArray *paths;
//  NSIndexSet *section = [NSIndexSet indexSetWithIndex:[newIndexPath section]];

    NSIndexPath *cellContentIndexPath;

    switch (type) {
        case NSFetchedResultsChangeInsert:
//          paths = [NSArray arrayWithObject:newIndexPath];
            if (![anObject isKindOfClass:[ChangeIssueDimensionValueHistoryItem class]]) {
                cellContentIndexPath = [NSIndexPath indexPathForRow:newIndexPath.row inSection:newIndexPath.section];
                paths = [NSArray arrayWithObject:cellContentIndexPath];
                [self.tableView insertRowsAtIndexPaths:paths 
                                      withRowAnimation:UITableViewRowAnimationFade];

                [self sendMessageAboutObjectsCountChanged];
            }

            break;
        case NSFetchedResultsChangeDelete:
            paths = [NSArray arrayWithObject:indexPath];
            [self.tableView deleteRowsAtIndexPaths:paths
                                   withRowAnimation:UITableViewRowAnimationFade];
            [self sendMessageAboutObjectsCountChanged];
            break;
        case NSFetchedResultsChangeMove:
            [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
                                        withRowAnimation:UITableViewRowAnimationFade];
            [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
                                        withRowAnimation:UITableViewRowAnimationFade];
            break;
        case NSFetchedResultsChangeUpdate:
            [self configureCell:[self.tableView cellForRowAtIndexPath:indexPath] 
           withIssueHistoryItem:[self.fetchedResultsController objectAtIndexPath:indexPath]];
            break;
        default:
            break;
    }

}

1 Ответ

2 голосов
/ 12 февраля 2012

Кажется, что это правильный способ, которым NSFetchedResultsController выполняет - реагируя на изменения на уровне модели (т.е. [managedObjectContext save]).

В документации: https://developer.apple.com/library/ios/#documentation/CoreData/Reference/NSFetchedResultsController_Class/Reference/Reference.html в разделе «Реагирование на изменения» указано, что контроллер не будет отображать изменения, пока контекст управляемого объекта не получит сообщение processPendingChanges. Это сообщение также может быть вызвано вручную.

...