gpt4 book ai didi

ios核心数据导入大量数据

转载 作者:行者123 更新时间:2023-11-28 22:13:58 28 4
gpt4 key购买 nike

我的应用程序需要从我的 Web API 导入对象(通常超过 5000 个对象),同时仍与数据库交互。目前,我将 API 设置为每个 API 请求返回 100 个对象。问题是我的性能受到了巨大的打击。导入所有数据可能需要 > 4 秒。大部分时间花在调用保存函数上。我已成功将导入推送到后台线程。但是,当我在每个 api 请求结束时将主上下文保存在主线程上时,可能需要 1 秒以上的时间才能保存,这会暂停所有滚动、动画等。我该怎么做才能将主上下文的保存放入的背景?

更新:这是一些示例代码

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

更新:我发现使用如上所述链接的上下文,如果我像在初始示例中那样重新创建背景上下文,那么一切似乎都正常。保存后台线程时仍然存在明显的延迟(我认为这是将更改传播到主线程的结果)。然而,这在性能上是一个很大的改进。

最佳答案

我不会从引入额外的私有(private)队列父 MOC 开始。

充其量它会稍微减少花在主线程上的总时间,同时增加完成导入的总挂钟时间。

当您仍在掌握 Core Data 框架本身时,我也不建议在 Core Data 之上使用第三方框架。

关于您关于处理 NSManagedObjectContextDidSaveNotification 的问题,如果像您在第一个示例中所示那样为每个摄取 block 临时创建了一个新的 bgContext,则没有必要根本无法处理这些通知,因为在子上下文中调用 save: 会立即透明地将更改传播到父上下文。

对于原始问题和示例,调用 save: 不应为 100 个对象花费 1 秒。

在理解为什么保存 100 个对象需要 1 秒钟之前,您不应该考虑架构更改(例如不同的上下文安排)。

将您的应用程序连接到仪器上,让告诉您什么一直在占用。答案可能会让您大吃一惊。

关于ios核心数据导入大量数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22238342/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com