我的應用程序需要從Web API(通常超過5000個對象)導入對象,同時仍與數據庫交互。目前我的API設置爲每個API請求返回100個對象。問題是我有巨大的表現。可能需要4秒鐘才能導入所有數據。大部分時間都是在調用save函數時花費的。我已經成功地將導入推入後臺線程。但是,當我在每個API請求結束時將主環境保存在主線程中時,可能需要1秒鐘以上的時間才能保存,這會暫停所有滾動,動畫等。我可以如何將主環境保存到的背景?ios核心數據導入大量數據
更新時間:下面是一些示例代碼
-(void) importLoop:(NSManagedObjectContext*)mainContext complete:(dispatch_block_t) complete{
[self apiRequest:^(NSArray *objects) {
if (objects.count == 0){ // nothing to load.
dispatch_async(dispatch_get_main_queue(), complete);
return;
}
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0ul);
dispatch_async(queue, ^{
NSManagedObjectContext* bgContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[bgContext setParentContext:mainContext];
[bgContext performBlock:^{
for (id object in objects){
// import data. This can take > 4 seconds
[bgContext save:nil]; // This can take > 1 second
// Note: This save merges the data to the main moc... but does not save the data to disk
}
[mainContext performBlock:^{
[mainContext save:nil]; // This can take > 1 second on main thread
[self importLoop:mainContext complete:complete]; // import next batch
}];
}];
});
}];
}
更新: 根據@Wain answer我需要設置以下
mainMoc - > mainThreadMoc - > bgMoc
其中
- mainMoc具有併發類型NSPrivateQueueConcurrencyType(這MOC用於保存到磁盤)
- mainThreadMoc具有併發類型NSMainQueueConcurrencyType是mainMoc的孩子
- bgMoc具有併發類型NSPrivateQueueConcurrencyType是mainThreadMoc
現在好了,我有這樣的設置,我有以下問題...當我對mainThreadMoc進行更改時,我該如何讓bgMoc知道它。我有一個註冊NSManagedObjectContextDidSaveNotification
- (void)managedObjectContextDidSaveNotification:(NSNotification *)notification
{
NSManagedObjectContext *savedContext = [notification object];
// ignore change notifications for the main MOC
if (self.mainMoc == savedContext)
{
return;
}
if (self.mainMoc.persistentStoreCoordinator != savedContext.persistentStoreCoordinator)
{
// that's another database
return;
}
if (savedContext == self.mainThreadMoc){
[self.mainMoc performBlock:^{
[self.mainMoc mergeChangesFromContextDidSaveNotification:notification];
}];
}else if (savedContext == self.bgMoc){
[self.mainThreadMoc performBlock:^{
[self.mainThreadMoc mergeChangesFromContextDidSaveNotification:notification];
}];
}
}
更新以下功能:我發現,與上下文鏈接正如我上面,如果提到我重新創建背景方面,正如我在最初的例子做接下來的事情似乎正在工作。當我保存後臺線程時(仍然會有明顯的延遲)(我認爲這是將更改傳播到主線程的結果)。然而這是一個很大的性能改善。
爲什麼不直接調用與導入相同的後臺線程保存? – brindy
從我所瞭解的Core Data處理過程中,不應該在不同的線程上使用相同的託管對象上下文。保存孩子moc將數據合併到主moc中。但是,要保存到磁盤,您需要保存主要的moc。真正的問題是,我仍然可以在導入過程中與主要moc進行交互,並將其保存在另一個線程中可能會導致一些主要問題 – datinc
您的主要上下文是直接連接到持久存儲協調器還是它也有父上下文? –