Core Data 的 NSPrivateQueueConcurrencyType 和线程间共享对象 [英] Core Data's NSPrivateQueueConcurrencyType and sharing objects between threads
问题描述
iOS 5 通过使用 NSPrivateQueueConcurrencyType
初始化 MOC,然后在 performBlock:
iOS 5 introduced a new way to quickly fetch data on a background thread by initializing the MOC using NSPrivateQueueConcurrencyType
and then doing the fetch in performBlock:
Core Data 的一个经验法则是您不能在线程/队列之间共享托管对象.performBlock:
是否仍然如此?以下是:
One of the rules of thumb of Core Data has been that you can not share a managed object between threads/queues. Is it still the case with performBlock:
? Is the following:
[context performBlock:^{
// fetch request code
NSArray *results = [context executeFetchRequest:request error:nil];
dispatch_async(dispatch_get_main_queue(), ^(void) {
Class *firstObject = [results objectAtIndex:0];
// do something with firstObject
});
}];
仍然不可接受,因为我在 bg 队列和主队列之间共享我的结果数组/对象?我还需要使用托管对象 ID 来做到这一点吗?
still unacceptable since I'm sharing my results array/objects between the bg queue and the main queue? Do I still need to use the managed object IDs to do that?
推荐答案
当您使用 NSPrivateQueueConcurrencyType
时,您需要做任何与上下文相关的事情或 -performBlock:
方法中属于该上下文的任何对象.
When you use NSPrivateQueueConcurrencyType
you need to do anything that touches that context or any object belonging to that context inside the -performBlock:
method.
您上面的代码是非法的,因为您将这些对象传递回主队列.不过,新 API 可以帮助您解决这个问题:您创建一个与主队列关联的上下文,即使用 NSMainQueueConcurrencyType
:
Your code above is illegal since you're passing those objects back to the main queue. The new API helps you in solving this, though: You create one context that's associated with the main queue, i.e. with NSMainQueueConcurrencyType
:
// Assume we have these two context (They need to be set up. Assume they are.)
NSManagedObjectContext *mainMOC = [[[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType] autorelease];
NSManagedObjectContext *backgroundMOC = [[[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType] autorelease];
// Now this can safely be called from ANY thread:
[backgroundMOC performBlock:^{
NSArray *results = [backgroundMOC executeFetchRequest:request error:nil];
for (NSManagedObject *mo in results) {
NSManagedObjectID *moid = [mo objectID];
[mainMOC performBlock:^{
NSManagedObject *mainMO = [mainMOC objectWithID:moid];
// Do stuff with 'mainMO'. Be careful NOT to use 'mo'.
}];
}
}];
如果您将内部 [mainMOC performBlock:]
调用移动到它自己的方法中,这会减少混淆.您可能还想将一组对象 ID 传递回主线程的上下文,而不是为每个对象 ID 执行一个块.这取决于您的需求.
This gets less confusing if you move the inner [mainMOC performBlock:]
call into its own method. You may also want to pass an array of object IDs back to the main thread's context in stead of executing a block for each object ID. It depends on your needs.
这篇关于Core Data 的 NSPrivateQueueConcurrencyType 和线程间共享对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!