didChangeObject: not called of NSFetchedResultsController

空扰寡人 提交于 2019-12-07 14:28:30

问题


I have nearly tried everything but cannot figure out what is wrong. I have a NSFetchedResultsController and fetch some posts out of core data. Then I have a method where I insert new posts into the same context and save the context. Normally, the didChangeObject: method should be called now, but it does not. I have a similar view controller where I do basically the same on a different table (=nsmanaged object) and there the didChangeObject: method gets called successfully.

What I have tried so far:

  • Created another context just for this view controller

  • Removed the cache of the NSFetchedResultsController

The following method fetches the data out of the core data db and 'stores' it into the NSFetchedResultsController (variable: 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);
    }
}

Furthermore, according to the documentation I set the delegate of the NSFetchedResultsController to my view controller (this is the same where the aforementioned fetch method is located).

In viewDidLoad:

self.controller.delegate = self;

Then I have implemented the methods from the protocol, also the 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;
    }

}

Then I have another method that stores some posts into core data. I think this is important: This method is invoked via a delegate from another thread. (The server connection invokes it using 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.
}

Does anyone have a hint or a suggestion what could be wrong?

Thanks and regards, Chris


回答1:


The problem is that you're setting the controller delegate in viewDidLoad and then later allocating a new controller in reloadNewsgroupsFromCoreData. Your newly allocated controller doesn't have the delegate set. Try setting the delegate directly in reloadNewsgroupsFromCoreData.

You typically don't want to allocate a new NSFetchedResultsController whenever something changes in your data. The entire point of using NSFetchedResultsController is to get delegate messages via NSFetchedResultsControllerDelegate when something changes. You only need to allocate a new NSFetchedResultsController if your fetch request changes. I suggest having another look at the Apple Docs.



来源:https://stackoverflow.com/questions/10894137/didchangeobject-not-called-of-nsfetchedresultscontroller

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!