I have a Core Data application which has a data structure of Articles & Comments (One to many relationship).
NSOperations manage the download and JSON parsing on a different thread then it uses mergeChangesFromContextDidSaveNotification to pass the changes to main thread where it's saved and a fetchedResultsController takes care of the tableView changes.
The calls for the articles and comments are in separate APIs called from the server and each has it's own NSOperation to handle the import. (They are based loosely around Apple's RSSImporter class but have been modified for JSON). Each operation has it's own context and uses the storeCoordinator from the fetchedResultsController.
commentParser.articleObjectID = [article objectID];
commentParser.persistentStoreCoordinator = [[self.fetchedResultsController managedObjectContext] persistentStoreCoordinator];
I'm trying to set the relationship in the NSOperation between the article and the comments and I believe I'm following the best practices by passing the objectID of the article into the comments operation and then using the object by doing the following:
Article *article = (Article *)[self.insertionContext objectWithID:articleObjectID];
Comment *aComment = (Comment *)[NSEntityDescription insertNewObjectForEntityForName:@"Comment" inManagedObjectContext:self.insertionContext];
[aComment setCommentArticle:article];
This seems to work fine but when going back to the root viewController where the tableView of original articles are, I'm getting the following error message:
* Terminating app due to uncaught exception 'NSObje开发者_如何学PythonctInaccessibleException', reason: 'The NSManagedObject with ID:0xdb24f30 has been invalidated.'
Any help with this would be appreciated!
You must save the new Core Data entities (or changes to existing ones) in the thread that creates them (to the persistent store) and then pass the object ID's out to your main thread where the NSManagedContext on that thread will use the objectID to retrieve the objects from the persistent store.
Have look at: http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/CoreData/Articles/cdConcurrency.html
So make sure you are saving the new objects (or changed objects) to the NSManagedObjectContext you created in the background thread and then everything should work fine.
Damien's got you on the right track. Here's how to approach this:
An object on your main thread is registered for
NSManagedObjectContextDidSaveNotification
The
NSOperation
downloads the JSON and adds them to a managed object context initialized within the operation, saving the context when all objects have been added.When the
NSManagedObjectContextDidSaveNotification
notification occurs, make sure that you are handling it on the main thread. If not, forward the message toself
on the main thread. (see Apple's sample codeTopSongs
for an example).When handling
NSManagedObjectContextDidSaveNotification
on the main thread, call[context mergeChangesFromContextDidSaveNotification:notification]
.Your
NSFetchedResultsController
will send the appropriate protocol messages to its delegate so you can update your UI.If you need to notify objects in your app in any other way, you can post an app specific notification that your objects can observe and do whatever they need to do.
You should NOT pass the object IDs back from your NSOperation to the main thread and insert them into the context again. You already did that in the NSOperation. If you need to know the new object IDs on your main thread that's fine to pass them and use them, but the objects have already been inserted and saved to your context.
One thing to check:
ManagedObjectIDs are just temporary IDs until the object is saved to a store. So, if you take an ID of a newly created object and hand it off to another thread/operation before the object has been saved, then it will have only a temporary ID which will change when the object is actually saved by any thread/operation.
I'm not sure from reading the description but it is likely that you are trying to find an object with a temporary ID that is no longer valid.
精彩评论