According to Daniel Eggert's answer in this question, when using a managed object context with NSPrivateQueueConcurrencyType
it's necessary to do anything that touches it or objects that belong to it within performBlock:
or performBlockAndWait:
Is the same true for NSMainQueueConcurrencyType
? Imagine the following code running on the main thread, in a UIViewController for instance:
self.moc = [[[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType] autorelease];
//moc setup
__block RHWidget *widget = nil;
[self.moc performBlockAndWait:^{
widget = [(RHWidget *)[self.moc objectWithID:self.widgetObjectID] retain];
}];
self.labelView.text = widget.descriptionString;
[widget release];
Is it safe to use the widget outside the block, since we know we're on the main thread? Or it is it necessary to do this:
__block NSString *description = nil;
[self.moc performBlockAndWait:^{
RHWidget *widget = (RHWidget *)[self.moc objectWithID:self.widgetObjectID];
description = [widget.descriptionString copy];
}];
self.labelView.text = description;
[description release];
Do things change if there's another NSManagedObjectContext
out there, possibly of the private queue type, doing work in blocks and pushing changes up to self.moc as a parentContext
?
This is a slightly contrived example of course, but it'd be nice to safely pass that widget to, for instance, a modal view controller that needs to access some of the widget's properties. Should I be passing the objectID of the widget instead and refetching it within performBlock:
in the new view controller?
To use Core Data in a multithreaded environment, ensure that: Managed object contexts are bound to the thread (queue) that they are associated with upon initialization. Managed objects retrieved from a context are bound to the same queue that the context is bound to.
Concurrency is the ability to work with the data on more than one queue at the same time. If you choose to use concurrency with Core Data, you also need to consider the application environment. For the most part, AppKit and UIKit are not thread-safe.
Getting Started Core Data (CRUD) with Swift. Core Data is a graphical and persistence framework, which is used in Apple devices with operating systems macOS and iOS. Core Data was first introduced in Mac OS X 10.4 Tiger and iOS with iPhone SDK 3.0.
Update: According to WWDC 2011 Session 303 (What's New in Core Data on iOS), NSMainQueueConcurrencyType
is intended to allow normal messaging on the main thread; you only need to use -performBlock:
when interacting with the context from a different thread. (Still-relevant parts of my original answer below.)
I've made an app or two that modifies Xcode's default "Master-Detail" app template to make the "main" MOC (created by the app delegate and passed among view controllers) main-queue-only, and parent to a private-queue context that I use for background operations like importing data from a web fetch. Thus, most uses of the context and its objects happen without being wrapped in performBlock:
. (The only time I do use performBlock:
is to push changes from the background-task context back to the main one to update the UI.) Works just fine.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With