2012-02-10 4 views
1

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

} 

ответ

2

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

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

+0

Благодарим вас за ответ! Но если я правильно понимаю, когда я добавляю новый объект в контекст, ему приходится запускать 'processPendingChanges'? Или нет? – hex

+1

Да, tableView должен обновиться, если NSSMetchedResultsController NSManagedObjectContext получит processPendingChanges. И (повторяя здесь) это происходит автоматически, когда контекст сохраняется. – JacobFennell

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