Nested UIManagedDocument contexts

I have read the docs on apples and still have a question that I cannot find an answer. I have a UIManagedDocument object that has two nested contexts: a child on the main thread and a parent on a private thread. And then I have the server side. So, when data comes in from the server, I want to insert it into my managed document on a background thread.

Is it thread safe to create an asynchronous queue, create an NSManagedObjectContext there, and set as the parent child context of the UIManagedDocument that is created on the main thread?

dispatch_queue_t fetchQ = dispatch_queue_create("Data fetcher", NULL);
dispatch_async(fetchQ, ^{
     //here goes some code for downloading data from the server

    NSManagedObjectContext * backgroundContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
    [backgroundContext setParentContext:self.eventDatabase.managedObjectContext]; // is this thread safe?

    //some code for creating objects in backgroundContext

    NSLog(@"inserting data in background thread");


});
dispatch_release(fetchQ);

      

In other words - is it safe for a thread to assign a context created on the parent thread of a private thread that was created on the main thread?

+3


source to share


2 answers


The private concurrency type is used. This means that you have to run the code on its own queue (via performBlock). So, if you want to do it, you have to do it like this:

NSManagedObjectContext * backgroundContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
backgroundContext.parentContext = self.eventDatabase.managedDocument;
backgroundContext.performBlock:^{
    //here goes some code for downloading data from the server
    //some code for creating objects in backgroundContext

    NSLog(@"inserting data in background thread");

    // Calling save on the background context will push the changes up to the document.
    NSError *error = nil;
    [backgroundContext save:&error];

    // Now, the changes will have been pushed into the MOC of the document, but
    // the auto-save will not have fired.  You must make this call to tell the document
    // that it can save recent changes.
    [self.eventDatabase updateChangeCount:UIDocumentChangeDone];
});

      



If you want to manage the queue yourself, you should probably use MOC constraints, you should start with NSConfinementConcurrencyType or with a standard init, because that is the default. Then it will look like this ...

dispatch_queue_t fetchQ = dispatch_queue_create("Data fetcher", NULL);
dispatch_async(fetchQ, ^{
    backgroundContext.parentContext = self.eventDatabase.managedDocument;

    //here goes some code for downloading data from the server

    NSManagedObjectContext * backgroundContext = [[NSManagedObjectContext alloc] init];

    // Everything else is as in the code above for the private MOC.
});
dispatch_release(fetchQ);

      

+4


source


There is no Andrew managed object that is not thread safe. To achieve what you want, you have to create a child managed context, make your stuff, and then save the changes in the child and parent context. remember that saving only pushes changes one level.



NSManagedObjectContext *addingContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[addingContext setParentContext:[self.fetchedResultsController managedObjectContext]];

[addingContext performBlock:^{
    // do your stuffs
    [addingContext save:&error];

    [parent performBlock:^{
        [parent save:&parentError];
    }];
}];

      

0


source







All Articles