這是一個已知的bug(嵌套的環境沒有得到時新對象將被保存永久標識)可以,並且應該被固定在即將推出的版本...
你應該能夠尋求永久的ID,雖然,但你只應該在已經插入的對象上請求它們。
[moc obtainPermanentIDsForObjects:moc.insertedObjects.allObjects error:0];
必須雖然節省了MOC之前做到這一點,因爲如果你不保存永久獲得的ID,臨時ID被傳播到父上下文。例如,在您保存到mainMoc的情況下,然後獲取IDS,backgroundMOC仍然具有臨時ID,因此將來保存會創建重複數據。
請注意,獲取永久ID一直到數據庫,但是如果您在主MOC的子MOC中執行此操作,則在發生這種情況時不應阻止主線程。
因此,在您保存您最低水平MOC,你應該切實有這樣的事情(在適當的錯誤處理,當然)...
[backgroundMoc performBlock:^{
[backgroundMoc obtainPermanentIDsForObjects:backgroundMoc.insertedObjects.allObjects error:0];
[backgroundMoc save:0];
[mainMoc performBlock:^{
[mainMoc save:0];
[masterMoc performBlock:^{
[masterMoc save:0];
}];
}];
}];
還有一些其他的遊戲,你可以玩,如果你想。
提供有關NSManagedObject類似於此類別...
@implementation NSManagedObject (initWithPermanentID)
- (id)initWithEntity:(NSEntityDescription *)entity insertWithPermanentIDIntoManagedObjectContext:(NSManagedObjectContext *)context {
if (self = [self initWithEntity:entity insertIntoManagedObjectContext:context]) {
NSError *error = nil;
if (![context obtainPermanentIDsForObjects:@[self] error:&error]) {
@throw [NSException exceptionWithName:@"CoreData Error" reason:error.localizedDescription userInfo:error.userInfo];
}
}
return self;
}
+ (NSArray*)createMultipleObjects:(NSUInteger)count withEntity:(NSEntityDescription *)entity inManagedObjectContext:(NSManagedObjectContext *)context {
NSMutableArray *array = [NSMutableArray arrayWithCapacity:count];
for (NSUInteger i = 0; i < count; ++i) {
[array addObject:[[self alloc] initWithEntity:entity insertIntoManagedObjectContext:context]];
}
NSError *error = nil;
if (![context obtainPermanentIDsForObjects:array error:&error]) {
@throw [NSException exceptionWithName:@"CoreData Error" reason:error.localizedDescription userInfo:error.userInfo];
}
return array;
}
@end
現在,在第一個,你付出去到數據庫中,併爲創建的每個實體的ID,但它不是很多,它發生在後臺線程中,並且每個dip都短...
噢,它不是最好的,但它提供了有用的。另外,第二個創建同一個對象的多個,並同時獲取它們的永久ID。
您也可以使用直接連接到PSC的MOC,並觀察DidChange事件,但這與舊的方式相同。
不幸的是,你不能擁有一個單獨的MOC只是發出persistentID請求並傳遞ObjectID,儘管你可以有一個獨立的MOC在數據庫中創建原型對象,並給你它們的ObjectID。
一個原型工廠是一個相當常見的模式,如果你走這條路線,當最終的錯誤修復到達這裏時,很容易做出微小的改變。
編輯
針對斯文...
如果要創建新的,複雜的圖表,那麼你需要創建後立即獲得一個永久編號。要減少商店的點擊次數,您應該全部創建它們,然後立即獲取ID,然後開始連接它們。
老實說,所有這些都是爲了解決當前存在的錯誤,這些錯誤值得中小型的更新工作。當錯誤得到修復時,你的代碼將是相同的(無法獲得)。所以,我建議這種方法適用於較小的進口。
如果您正在進行大規模更新,我建議使用「舊」方法。創建一個直接連接到PSC的新MOC。在那裏進行所有更改,並讓您的「實時」上下文僅從這些DidSave通知合併。
最後,對永久性ID的數據庫影響。放棄MOC是可以的。磁盤被擊中,元數據被改變,但對象不被持久化。
說實話,我沒有做一個大的測試,看看是否有空的空間,所以你可能想要這樣做,並回到我身邊。
查看磁盤上的實際數據庫文件大小,然後創建10000個對象,然後獲取持久ID,釋放MOC並再次查看大小。
如果有影響,您可以嘗試刪除對象,或在大型更新後對數據庫運行真空以查看是否有效。
如果您打算創建大量可能會丟失的對象,則無需點擊數據庫。您可能希望直接附加到PSC並使用舊的忠實通知。
@Sven你爲什麼給這個獎勵呢?你有類似的問題嗎? – Snowman
是的,這幾乎是我面對的同樣的問題。 – Sven
我的「解決方案」是擺脫主/主/子設置,只使用主/子,以便持久性存儲鏈接到主隊列而不是背景隊列。 – Snowman