问题
I am using a NSFetchedResultsController
in combination with a UIManagedDocument
which gets updated in an background thread.
I have set up the NSFetchedResultsController exactly as described in this tutorial: How To Use NSFetchedResultsController
I have set the delegate _fetchedResultsController.delegate = self
and the protocol for my view controller to NSFetchedResultsControllerDelegate
.
My code works fine when it loads the data after launch. However, the NSFetchedResultsController
does not update the TableView whenever it has processed and saved the data in the background thread. In particular, the NSFetchedResultsController's delegate methods -controllerWillChangeContent:controller
etc. are never being called.
I have double-checked that the SQLite database contains the data correctly. This is how I process and save the data in the view controller:
[backgroundContext performBlock:^{
[company parseAttributesFrom:xmlStr inManagedObjectContext:backgroundContext]; //self.managedDocument.managedObjectContext
NSError *error = nil;
[backgroundContext save:&error];
if (error) NSLog(@"error: %@",error.localizedDescription);
[self.managedDocument.managedObjectContext performBlock:^{
NSError *error = nil;
[self.managedDocument.managedObjectContext save:&error];
if (error) NSLog(@"error: %@",error.localizedDescription);
}];
[self.managedDocument saveToURL:self.managedDocument.fileURL forSaveOperation:UIDocumentSaveForOverwriting completionHandler:NULL];
[self.managedDocument updateChangeCount:UIDocumentChangeDone];
}];
How can I get the NSFetchedResultsController to update the TableView automatically when the underlying data changes?
Thank you for your help!
回答1:
I think that reason is in managedObjectContext. You make changes in background, and NSFetchedResultsController
fetches from the main one. So you need to merge changes to that one context by adding an observer of changes in context
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(contextChanged:) name:NSManagedObjectContextDidSaveNotification object:nil];
Here is a great tutorial by Marcus Zarra - The Guru of Core Data) Hope that helps. http://www.cimgf.com/2011/08/22/importing-and-displaying-large-data-sets-in-core-data/
回答2:
I would suggest, when using UIManagedDocument, that you make your background context a child of the main context.
backgroundContext = [[NSManagedContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
backgroundContext.parent = self.managedDocument.managedObjectContext;
Now, you can do what you want in the background context, and when you want to save the background context, the changes will be stuffed into the main context. Of course, you will still need to save the UIManagedDocument, but that is done "seamlessly" in the background again, via setting the ChangeDone count.
[backgroundContext performBlock:^{
[company parseAttributesFrom:xmlStr inManagedObjectContext:backgroundContext]; //self.managedDocument.managedObjectContext
NSError *error = nil;
[backgroundContext save:&error];
if (error) NSLog(@"error: %@",error.localizedDescription);
// NOTE: Now, the changes have been pushed into the main context of your document.
// DO NOT call save directly on the managed document context.
[self.managedDocument.managedObjectContext performBlock:^{
[self.managedDocument updateChangeCount:UIDocumentChangeDone];
}];
}];
Now, your background context just goes away, your main context sees the changes, and the document is saved.
来源:https://stackoverflow.com/questions/11192916/nsfetchedresultscontroller-does-not-update-tableview-after-uimanageddocuments-ge