我的应用程序需要从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
您的主要上下文是直接连接到持久存储协调器还是它也有父上下文? –