Concurrency
并发是在同一时间在多个队列中操作数据的能力。如果选择使用core data并发操作,你同样需要考虑应用程序的环境。appkit和uikit都不是线程安全的。特别是os x,如果你要使用这些技术,多线程可能会很复杂。
Core Data, Multithreading, and the Main Thread
core data,managed object context可以使用两种病发的形式。NSMainQueueConcurrencyType
和NSPrivateQueueConcurrencyType
.
NSMainQueueConcurrencyType
主要应用于你的应用程序的interface并且只能用在主队列中。
NSPrivateQueueConcurrencyType
创建自己的队列并且只能在其创建的队列中使用。因为队列是私有的并且是NSManagedObjectContext
的内部实例,他只能通过performBlock:
和performBlockAndWait:
方法来执行。
In both cases, the initialization of the NSManagedObjectContext
instance is the same:
NSManagedObjectContext *moc = [[NSManagedObjectContextalloc] initWithConcurrencyType:<#type#>];
let moc =NSManagedObjectContext(concurrencyType:<#type#>)
The parameter being passed in as part of the initialization will determine what type ofNSManagedObjectContext
is returned.
Using a Private Queue to Support Concurrency
通常情况下,需要避免在主队列中执行数据操作。有可能导致用户交互无法响应。如果你的应用程序会操作数据,例如从json将数据import到core data,创建一个私有的队列context。例子如下:
NSArray *jsonArray= …; //JSON data to be imported into Core Data
NSManagedObjectContext *moc = …;//Our primary context on the main queue
NSManagedObjectContext *private = [[NSManagedObjectContextalloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[privatesetParentContext:moc];
[privateperformBlock:^{
for (NSDictionary*jsonObject injsonArray) {
NSManagedObject *mo = …;//Managed object that matches the incoming JSON structure
//update MO with data from the dictionary
}
NSError *error= nil;
if (![privatesave:&error]){
NSLog(@"Error saving context: %@\n%@",[error localizedDescription],[error userInfo]);
abort();
}
[moc performBlockAndWait:^{
NSError *error= nil;
if (![mocsave:&error]){
NSLog(@"Error saving context: %@\n%@",[error localizedDescription],[error userInfo]);
abort();
}
}];
}];
let jsonArray = …//JSON data to be imported into Core Data
let moc = …//Our primary context on the main queue
let privateMOC =NSManagedObjectContext(concurrencyType: .PrivateQueueConcurrencyType)
privateMOC.parentContext =moc
privateMOC.performBlock {
for jsonObjectin jsonArray {
let mo = …//Managed object that matches the incoming JSON structure
//update MO with data from the dictionary
}
do {
try privateMOC.save()
moc.performBlockAndWait {
do {
try moc.save()
} catch {
fatalError("Failure to save context:\(error)")
}
}
} catch {
fatalError("Failure to save context:\(error)")
}
}
在这个例子中,数组接收json。然后你创建一个新的NSManagedObjectContext
被定义为一个私有的队列。这个新的context被设置为应用程序运行的主队列的child。调用performBlock:
并且执行NSManagedObject
来创建。一旦所有的数据被转换为NSManagedObject
实例,你可以在私有context中调用save,这会移除所有主队列上的改变而且不会block主队列。
Passing References Between Queues
NSManagedObject
instances are not intended to be passed between queues. Doing so can result in corruption of the data and termination of the application. When it is necessary to hand off a managed object reference from one queue to another, it must be done throughNSManagedObjectID
instances.
You retrieve the managed object ID of a managed object by calling theobjectID
method on theNSManagedObject
instance.