![](/img/trans.png)
[英]Saving managed object context creates deadlock in iOS 5's performBlock
[英]Should Core Data Managed Object creation occur within the Managed Object Context's `performBlock:` call?
我最近開始嘗試使用Core Data的更新的initWithConcurrencyType:NSPrivateQueueConcurrencyType
構建托管對象上下文。 使用這種類型的MOC時,我們應該使用performBlock:
或performBlockAndWait:
以“確保在為上下文指定的隊列上執行塊操作”。
作為其中的一部分我感動的托管對象的創建調用initWithEntity:insertIntoManagedObjectContext:
里面 performBlock:
塊,要在MOC的私人隊列中運行。
這與Apple的Core Data Concurrency文章中顯示的策略相匹配:
[private performBlock:^{
for (NSDictionary *jsonObject in jsonArray) {
NSManagedObject *mo = ... ; //Managed object that matches the incoming JSON structure
}
NSError *error = nil;
if (![private save:&error]) {
NSLog(@"Error saving context: %@\n%@", [error localizedDescription], [error userInfo]);
abort();
}
}];
我發現自己在void
方法中初始化了托管對象,這些方法實際上在完成塊中返回了新創建的對象。
+ (void)managedObjectFromJSON:(NSDictionary *)json completion:(void (^)(XYZManagedObject *object))completion;
與僅從JSON解析方法返回對象相比,此體系結構引入了復雜性。 我似乎還遇到了與此設計相關的並發問題/崩潰,也許是在這些完成模塊構造函數中鏈在一起鏈接的受管理對象的異步負載中。
我的每個受管對象都執行以下操作,並通過performBlock:
塊中調用的完成塊返回創建的對象。
[managedObjectContextPrivateQueue performBlock:^{
NSEntityDescription *entity = [NSEntityDescription entityForName:@"entity" inManagedObjectContext:managedObjectContextPrivateQueue];
XYZManagedObject *managedObject = [[XYZManagedObject alloc] initWithEntity:entity insertIntoManagedObjectContext:managedObjectContextPrivateQueue];
[managedObjectContextPrivateQueue save:&error]
completion(managedObject);
}];
或者,是否可以在performBlock:
塊之外創建托管對象,而只在其中移動插入/保存操作? 請注意, NSEntityDescription
方法確實需要訪問塊外部的MOC。
NSEntityDescription *entity = [NSEntityDescription entityForName:@"entity" inManagedObjectContext:managedObjectContextPrivateQueue];
XYZManagedObject *managedObject = [[XYZManagedObject alloc] initWithEntity:entity insertIntoManagedObjectContext:nil];
[managedObjectContextPrivateQueue performBlock:^{
[managedObjectContextPrivateQueue insertObject:managedObject];
[managedObjectContextPrivateQueue save:&error]
}];
return managedObject;
或者,也許我應該使用performBlockAndWait:
等待塊運行,然后直接從方法而不是從完成塊返回托管對象。
當應通過performBlock:
private隊列路由被管理對象上下文調用時,應如何創建和返回被管理對象?
您可以在MOC之外創建托管對象。 請參見-[NSManagedObjectContext insertObject:]
。
但是,您可能一般不想這樣做。 如果要創建條件對象,這很有用。 例如,如果您有一個代表用戶可能編輯的內容的托管對象,則可以創建一個非托管版本進行編輯,並且僅在用戶保存更改時才插入MOC。 這不是最好的方法,但是可以。
但是,您的問題實際上是關於MOC的異步操作。 我的觀點是,最好的辦法是查看處理托管對象的每個API,並弄清楚如何使它們正確異步。 除非您知道調用者在同一個MOC的performBlock{AndWait}:
運行,否則絕對不要從方法返回托管對象。 這是因為無法(可靠地)從創建對象的MOC外部訪問這些對象。
您可以返回objectID
,並讓調用者獲取關聯的對象。 它通常比較繁瑣且效率較低,但是它是跨越MOC邊界時唯一可靠的解決方案。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.