문제

It is briefly mentioned in UIManagedDocument's documentation that

To support asynchronous data writing, Core Data actually uses a pair of nested managed object contexts.

Is that specific to UIManagedDocument or Core Data always does that?

The same document also states that

If appropriate, you can load data from a background thread directly to the parent context.

Does that mean that in the following code

NSManagedObjectContext *moc = self.managedObjectContext;
[moc performBlock:^() {
    Record *record = [NSEntityDescription
        insertNewObjectForEntityForName:@"Record" 
                 inManagedObjectContext:moc];
}];

I should simply replace first line by

NSManagedObjectContext *moc = self.managedObjectContext.parentContext;

to accomplish that?

I guess I'm also confused about where it would be "appropriate" to use this parent context directly. I mean it already sounds like that performBlock is meant to be used to unload tasks to the background queue. Why would I need to mess with the parent context?

I would greatly appreciate if somebody clarifies all that for me.

도움이 되었습니까?

해결책

This is an implementation detail of UIManagedDocument, however this is a common design pattern in Core Data applications. The managedObjectContext of UIManagedDocument is a context with concurrency type of NSMainQueueConcurrencyType, while the parentContext is a context with concurrency type of NSPrivateQueueConcurrencyType.

For more information about concurrency types, see here. In short, the parent context uses background queue for its operations, while the child uses the main queue.

Typically, you'd want to work directly with the parent context when you wish to perform something in a non-blocking fashion, in a background queue. For instance, if you wish to perform a long and difficult fetch request, you could perform it directly on the parent context. Remember, objects returned are not interchangeable between contexts, so you would have to refetch the returned objects from one context into the other (but refetching can be now easily performed with the [NSPredicate predicateWithFormat:@"SELF IN %@", fetchedObjectsFromAnotherContext]).

So to conclude, it depends on what you do in the operation. Main queue context simplifies things a lot by not requiring you to use performBlock:, since everything is performed on the main queue (main thread). If you only wish to insert an object, the benefit of moving to a private queue would be negligible, or indeed, even detrimental due to the context switch by the OS. However, if in order to perform this object insertion, you need to perform heavy lifting, you could offload it to a background queue and perform it directly on the parent context.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top