UIManagedDocument嵌套的上下文

时间:2012-04-10 11:07:31

标签: iphone core-data nsmanagedobjectcontext uimanageddocument

我一直在阅读苹果文件,但仍有一个问题,我无法找到答案。我有一个UIManagedDocument对象,它有两个嵌套的上下文 - 一个在主线程上,一个在父线程上。接下来,我有一个服务器端。因此,当数据从服务器到达时,我想在后台线程中将其插入到我的托管文档中。

是否线程安全,创建异步队列,在那里创建一个NSManagedObjectContext并设置为在主线程中创建的父UIManagedDocument的子上下文?

dispatch_queue_t fetchQ = dispatch_queue_create("Data fetcher", NULL);
dispatch_async(fetchQ, ^{
     //here goes some code for downloading data from the server

    NSManagedObjectContext * backgroundContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
    [backgroundContext setParentContext:self.eventDatabase.managedObjectContext]; // is this thread safe?

    //some code for creating objects in backgroundContext

    NSLog(@"inserting data in background thread");


});
dispatch_release(fetchQ);

换句话说 - 是否可以线程安全地分配给在主线程上创建的私有线程父项创建的上下文?

2 个答案:

答案 0 :(得分:4)

您正在使用私有并发类型。这意味着,您应该在自己的队列上运行代码(通过performBlock)。所以,如果你想这样做,你应该这样做......

NSManagedObjectContext * backgroundContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
backgroundContext.parentContext = self.eventDatabase.managedDocument;
backgroundContext.performBlock:^{
    //here goes some code for downloading data from the server
    //some code for creating objects in backgroundContext

    NSLog(@"inserting data in background thread");

    // Calling save on the background context will push the changes up to the document.
    NSError *error = nil;
    [backgroundContext save:&error];

    // Now, the changes will have been pushed into the MOC of the document, but
    // the auto-save will not have fired.  You must make this call to tell the document
    // that it can save recent changes.
    [self.eventDatabase updateChangeCount:UIDocumentChangeDone];
});

如果你想自己管理队列,你应该使用一个限制MOC,你应该使用NSConfinementConcurrencyType初始化,或者使用标准init,因为这是默认值。然后,它看起来像这样......

dispatch_queue_t fetchQ = dispatch_queue_create("Data fetcher", NULL);
dispatch_async(fetchQ, ^{
    backgroundContext.parentContext = self.eventDatabase.managedDocument;

    //here goes some code for downloading data from the server

    NSManagedObjectContext * backgroundContext = [[NSManagedObjectContext alloc] init];

    // Everything else is as in the code above for the private MOC.
});
dispatch_release(fetchQ);

答案 1 :(得分:0)

没有Andrew managedobjectcontext不是线程安全的。要实现您想要的功能,您必须创建一个子managedcontext,执行您的工作,然后在子和父上下文中保存更改。请记住,保存仅将更改推高一级。

NSManagedObjectContext *addingContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[addingContext setParentContext:[self.fetchedResultsController managedObjectContext]];

[addingContext performBlock:^{
    // do your stuffs
    [addingContext save:&error];

    [parent performBlock:^{
        [parent save:&parentError];
    }];
}];