Master Data and NSOperation

I am currently working with a subclass NSPersistentDocumentthat uses NSOperationto import data in the background. According to the documentation, I am observing NSManagedObjectContextDidSaveNotificationafter saving in the background job and distributing the notification to NSManagedObjectContextthe main thread using -mergeChangesFromContextDidSaveNotification:.

Everything works fine, but it is a weird workflow for a user who imports data into a new document. They need to save an empty document before importing (otherwise it -save:will fail because the document didn’t configure the URL for NSPersistentStoreCoordinator.) I don’t see a path around this, except for some kind of “new” Document Setup Wizard that provides it -writeToURL:ofType:forSaveOperation:originalContentsURL:error:is called before importing .

Also, it seems that the import task in the background eliminates the use of NSUndoManagerthe main thread. (I assume that it is not safe to share the thread deletion manager of the managed object context.) From the user's point of view, there is no way to cancel all new objects created during import.

I read both the master data programming guide and the book by Marcus Zarra, but I'm still new to this aspect of the structure. I hope I missed something: if not, I will adapt my application to these restrictions (the benefits of Core Data far outweigh these limitations of the user interface.)

Thank you for your time!

-

Based on Peter Hosey’s suggestion below, I added the following code to create temporary storage before import:

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:&error];
    if (! persistentStore) {
        NSLog(@"error = %@", error); // TODO: better error handling
    }
}

SQLite URL-:

- (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:&error];
            if (! newPersistentStore) {
                NSLog(@"error = %@", error); // TODO: better error handling
            }
        }
    }

    return [super writeToURL:absoluteURL ofType:typeName forSaveOperation:saveOperation originalContentsURL:absoluteOriginalContentsURL error:error];
}
+5
4

Core Data, , , , ( ) . migratePersistentStore:toURL:options:withType:error:, - . . ( , ).

+5

/ , , , ( / ). , , , .

+2

100% Mac, , , , sql/plist .

Potentially, it would be even better to create persistent storage on disk in a standard temporary directory and move it when the user clicks on save.

+2
source

Have you tried setting up a temporary file URL when setting up the coordinator? You should be able to undo -mergeChangesFromContextDidSaveNotification: in the main thread. There is no need to register a cancel manager for the MOC in the background thread.

0
source

All Articles