4

我正在从后台队列创建许多托管对象并将其添加到 Core Data。我的理解是我无法从后台线程访问上下文,因此我使用 performBlock 来安排将 Core Data 添加回创建上下文的同一队列中。这工作得很好......

我的问题是在测试期间我注意到通过删除[moc performBlock:^{ ... }];应用程序仍然可以按预期执行(甚至可能快几分之一秒)我需要performBlock吗?我会假设我这样做并且它只是以非线程安全的方式工作(目前:),我只是想检查以确保我的理解没有缺陷。

dispatch_queue_t backgroundQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
dispatch_async(backgroundQueue, ^{ 
    // GET DATA
    // PROCESS DATA
    NSManagedObjectContext *context = [[self managedDocument] managedObjectContext];
    [moc performBlock:^{
          // ADD TO CORE DATA
          [Core createRodInContext:context withDictionary:fuelRodDictionary];
     }];

});

编辑:为 createRodInContext 添加了实现 ...

+ (Rod *)createRodInContext:(NSManagedObjectContext *)context withDictionary:(NSDictionary *)dictionary {

    // CREATE
    Rod *rod = [NSEntityDescription insertNewObjectForEntityForName:@"Rod" inManagedObjectContext:context];

    // POPULATE
    [neo setDataCode:[dictionary objectForKey:@"dataCode"]];
    [neo setDataName:[dictionary objectForKey:@"dataName"]];
    [neo setDataReference:[dictionary objectForKey:@"dataReference"]];
    ...
    return rod;
}
4

1 回答 1

5

在后台线程中,您必须使用 [moc performBlock:^{ ... }]在主托管对象上下文中插入(和填充)托管对象。

省略performBlock意味着您也在不同的线程(与后台队列相关联)中使用托管对象上下文(在主线程上创建)。

这可能是偶然的,但是一旦主线程与您的后台线程在同一时刻访问 MOC,结果是不可预测的,因为(正如您已经说过的),MOC 不是线程安全的。

另请参阅OS X v10.7 和 iOS 5.0 的核心数据发行说明中对托管对象上下文的并发支持

限制(NSConfinementConcurrencyType)。

这是默认设置。您保证上下文不会被除您创建它的线程之外的任何线程使用。

但是对于其他并发类型(私有队列、主队列),除非您的代码已经在与 MOC 关联的队列上执行,否则您始终必须使用performBlock(或)。performBlockAndWait

于 2012-11-25T18:36:20.537 回答