Core Data 的 NSPrivateQueueConcurrencyType 和线程间共享对象 [英] Core Data's NSPrivateQueueConcurrencyType and sharing objects between threads

查看:17
本文介绍了Core Data 的 NSPrivateQueueConcurrencyType 和线程间共享对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆