2012-02-10 18 views
1

私のひどい英語を申し訳ありません。 私のiOSアプリに大きな問題があります。アプリケーションにはCore Dataによって管理される大きなデータベースがあります。そして、私はこのデータを表示するための多くのTableViewコントローラを持っています。データベースの変更はすべて、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

はい、NSFetchedResultsControllerのNSManagedObjectContextがprocessPendingChangesを受け取った場合、tableViewは更新されます。コンテキストが保存されると、これが自動的に行われます(ここで繰り返します)。 – JacobFennell

関連する問題