2012-04-10 113 views
3

我一直在阅读苹果文件,仍然有一个问题,我无法找到答案。我有一个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); 

换句话说 - 是线程安全的分配到这是一个私人的线程父创建了一个背景下,这是一个主线程产生的?

回答

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); 
+0

BTW,不要忘记调用[backgroundContext节省:错误]或变化不会被推到父上下文。 – 2012-04-12 14:49:12

+0

为什么不使用UIManagedDocument的parentContex,这个上下文在后台运行? – 2013-02-18 14:01:25

0

否Andrew managedobjectcontext不是线程安全的。为了实现你想要的,你必须创建一个child托管上下文,做你的事情,然后保存更改上的孩子和父上下文。请记住,保存只会将更改推上一个级别。

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

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

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