3

私はほとんどすべてを試しましたが、何が悪いのか理解できません。NSFetchedResultsControllerがあり、コアデータからいくつかの投稿をフェッチしています。次に、同じコンテキストに新しい投稿を挿入してコンテキストを保存するメソッドがあります。通常、didChangeObject:メソッドを今すぐ呼び出す必要がありますが、呼び出さないでください。私は同じようなViewControllerを持っており、基本的に同じことを別のテーブル(= nsmanagedオブジェクト)で実行し、didChangeObject:メソッドが正常に呼び出されます。

私がこれまでに試したこと:

  • このViewController専用に別のコンテキストを作成しました

  • NSFetchedResultsControllerのキャッシュを削除しました

次のメソッドは、コアデータデータベースからデータをフェッチし、それをNSFetchedResultsController(変数:)に「格納」しますcontroller

//reloading newsgroups from coredata
- (void)reloadNewsgroupsFromCoreData
{    
    //creating fetch request
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"Post"];

    //sorting by transient date (hour and secons cutted off)
    NSSortDescriptor *sortByDate = [[NSSortDescriptor alloc] initWithKey:@"dateCreatedTransient" ascending:NO];
    NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortByDate, nil];
    [fetchRequest setSortDescriptors:sortDescriptors];

    //where clause
    [fetchRequest setPredicate:[NSPredicate predicateWithFormat:@"ref_subscribed_newsgroup == %@ AND references == nil", self.newsgroup]];

    //setting fetchrequest
    self.controller = [[NSFetchedResultsController alloc]
                       initWithFetchRequest:fetchRequest
                       managedObjectContext:self.context
                       sectionNameKeyPath:@"dateCreatedForSections"
                       cacheName:nil]; //todo, maybe add a cache here!

    //fetch
    NSError *error;
    [self.controller performFetch:&error];

    if (error) {
        NSLog(@"%@", error);
    }
}

さらに、ドキュメントによると、NSFetchedResultsControllerのデリゲートをビューコントローラーに設定しました(これは、前述のフェッチメソッドが配置されている場所と同じです)。

viewDidLoad

self.controller.delegate = self;

次に、プロトコルからメソッドを実装しました。didChangeObject:

- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath {    
    UITableView *tableView = self.tableView;   

  // I HAVE ADDED A BREAKPOINT HERE BUT IT NEVER STOPS HERE.

    switch(type) {

        case NSFetchedResultsChangeInsert:
            [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];

            break;
        case NSFetchedResultsChangeDelete:
            [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
            break;

        case NSFetchedResultsChangeUpdate:
            [self configureCell:[tableView cellForRowAtIndexPath:indexPath]
                    atIndexPath:indexPath];

            break;

        case NSFetchedResultsChangeMove:
            [tableView deleteRowsAtIndexPaths:[NSArray
                                               arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
            [tableView insertRowsAtIndexPaths:[NSArray
                                               arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
            break;
    }

}

次に、いくつかの投稿をコアデータに保存する別の方法があります。これは重要だと思います。このメソッドは、別のスレッドからのデリゲートを介して呼び出されます。(サーバー接続はを使用してそれを呼び出しますperformSelectorOnMainThread:...

- (void)storeIntoCoreData:(NSArray*)postsArray
{ 
...
        Post *entity = [NSEntityDescription insertNewObjectForEntityForName: @"Post" inManagedObjectContext:context];

        entity.inReply = dummy.in_reply;
        entity.body = dummy.body;
        entity.email = dummy.email;
        entity.from = dummy.from;
        entity.messageIdentifier = dummy.message_identifier;
        entity.references = dummy.references;
        entity.subject = dummy.subject;
        entity.dateCreated = dummy.date;
        entity.unread = [NSNumber numberWithInt:1];
...
    [self.context save:&error];
    if (error)
    {
        NSLog(@"error: %@", error);
    }

// IMPORTANT: CURRENTLY I AM CALLING THIS METHOD AGAIN HERE, WHICH 
// FETCHES ALL POSTS OUT OF CORE DATA.
// THIS IS SO UGLY AND NOT PERFORMANT. 
// THEN I INVOKE RELOADDATA ON THE TABLEVIEW TO RELOAD THE ENTIRE TABLE
// BUT THERE WAS JUST ONE INSERT SO A ENTIRE RELOAD WOULD NOT BE NECESSARY. 
    [self reloadNewsgroupsFromCoreData];
    [self.tableView reloadData];

// I HAVE TO DO THIS BECAUSE THE didChangeObject METHOD GETS NOT CALLED.
}

誰かが間違っている可能性のあるヒントや提案を持っていますか?

ありがとう、よろしく、クリス

4

1 に答える 1

4

問題は、でコントローラーデリゲートを設定しviewDidLoad、後でで新しいコントローラーを割り当てることreloadNewsgroupsFromCoreDataです。新しく割り当てられたコントローラにはデリゲートが設定されていません。でデリゲートを直接設定してみてくださいreloadNewsgroupsFromCoreData

NSFetchedResultsController通常、データに何か変更があった場合は常に新しいデータを割り当てたくありません。使用の全体的なポイントは、何かが変更されたときにNSFetchedResultsController経由してデリゲートメッセージを取得することです。フェッチ要求が変更された場合NSFetchedResultsControllerDelegateにのみ、新しいものを割り当てる必要があります。AppleDocsNSFetchedResultsControllerをもう一度見てみることをお勧めします。

于 2012-06-29T06:09:16.627 に答える