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]; 
    }]; 
}];