简体   繁体   中英

iOS background save in Core Data

I want to ensure that my main thread never blocks, that's why I want to do my Core Data saves in the background.

I've been reading the Apple docs together with this link (and many others, but I found this one pretty useful): http://www.cocoanetics.com/2012/07/multi-context-coredata/ , though I cannot get the architecture right.

In my AppDelegate.m:

- (NSManagedObjectContext *)managedObjectContext
{
    if (_managedObjectContext != nil) {
        return _managedObjectContext;
    }

    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
    if (coordinator != nil) {
        _saveContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
        [_saveContext setPersistentStoreCoordinator:coordinator];

        _managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
        [_managedObjectContext setParentContext:_saveContext];
    }
    return _managedObjectContext;
}

Then to save, I would do something like this:

// var 'context' is the context coming from method managedObjectContext
// this code is in the same thread 'context' is created in (the main thread)
NSError *error = nil;
if ([context save:&error]) {
    [context.parentContext performBlock:^{
        NSError *err = nil;
        if(![context.parentContext save:&err]) {
            NSLog(@"Error while saving context to the persistent store");
        }
    }];
} else {
    // handle error
}

This is what I would get from reading the link I supplied earlier. Saving does not work, once the app is closed and reopened, the changes made to any managed objects are gone: they were never saved to the persisted store.

Makes sense I guess since I created 2 NSManagedObjectContexts in 1 thread, Apple docs clearly state to have only 1 NSManagedObjectContext per thread. So how do I setup the parent/child relation between _managedObjectContext and _saveContext? I know _saveContext needs to be initialised in another thread, but I cannot get this approach to work.

(From the comments)

All the "new" managed object context types ( NSMainQueueConcurrencyType , NSPrivateQueueConcurrencyType ) manage their own threads, it is not necessary to create the context on a special thread. The only thing to remember is always to use performBlock or performBlockAndWait for operations in the context. This ensures that the operations are executed on the right queue and thread.

So your code is OK.

(As it turned out, the error was that a wrong context was passed to your saving routine and therefore the inner save was not done in the top-level context.)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM