Note that there are some explanatory texts on larger screens.

plurals
  1. POCore Data and NSOperation
    text
    copied!<p>I'm currently working with an <code>NSPersistentDocument</code> subclass that uses <code>NSOperation</code> to import data in the background. As per the documentation, I'm observing the <code>NSManagedObjectContextDidSaveNotification</code> after saving in the background task and propagating the notification to the <code>NSManagedObjectContext</code> in the main thread using <code>-mergeChangesFromContextDidSaveNotification:</code>.</p> <p>Everything works fine, but it presents a weird workflow for a user who's importing data into a new document. They need to save an empty document before doing the import (otherwise the <code>-save:</code> fails because the document hasn't configured a URL for the <code>NSPersistentStoreCoordinator</code>.) I don't see a way around this other than some kind of "new document setup" wizard that ensures <code>-writeToURL:ofType:forSaveOperation:originalContentsURL:error:</code> gets called before the import.</p> <p>Also, it appears that an import task in the background precludes the use of an <code>NSUndoManager</code> on the main thread. (I'm assuming that it's unsafe to share the managed object context's undo manager across the threads.) From a user's point-of-view, there's no way to undo all the new objects created during the import.</p> <p>I've read both the <em>Core Data Programming Guide</em> and Marcus Zarra's book, but I'm still new to this aspect of the framework. Hopefully, I've overlooked something: if not, I'll adapt my app to these restrictions (the benefits of Core Data far outweigh these user interface limitations.)</p> <p>Thanks for your time!</p> <p>--</p> <p>Based on Peter Hosey's suggestion below, I added the following code to create a temporary persistent store prior to the import:</p> <pre><code>NSPersistentStoreCoordinator *persistentStoreCoordinator = [self.managedObjectContext persistentStoreCoordinator]; if ([[persistentStoreCoordinator persistentStores] count] == 0) { // create an in-memory store to use temporarily NSError *error; NSPersistentStore *persistentStore = [persistentStoreCoordinator addPersistentStoreWithType:NSInMemoryStoreType configuration:nil URL:nil options:nil error:&amp;error]; if (! persistentStore) { NSLog(@"error = %@", error); // TODO: better error handling } } </code></pre> <p>Then, after a file is selected in the save panel, the temporary persistent store is migrated to a SQLite store at the selected URL:</p> <pre><code>- (BOOL)writeToURL:(NSURL *)absoluteURL ofType:(NSString *)typeName forSaveOperation:(NSSaveOperationType)saveOperation originalContentsURL:(NSURL *)absoluteOriginalContentsURL error:(NSError **)error { NSPersistentStoreCoordinator *persistentStoreCoordinator = [self.managedObjectContext persistentStoreCoordinator]; for (NSPersistentStore *persistentStore in [persistentStoreCoordinator persistentStores]) { if (persistentStore.type == NSInMemoryStoreType) { // migrate the in-memory store to a SQLite store NSError *error; NSPersistentStore *newPersistentStore = [persistentStoreCoordinator migratePersistentStore:persistentStore toURL:absoluteURL options:nil withType:NSSQLiteStoreType error:&amp;error]; if (! newPersistentStore) { NSLog(@"error = %@", error); // TODO: better error handling } } } return [super writeToURL:absoluteURL ofType:typeName forSaveOperation:saveOperation originalContentsURL:absoluteOriginalContentsURL error:error]; } </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload