Multithreading 核心数据多线程和嵌套上下文
我刚刚开始学习核心数据编程。我尝试制作一个示例,其中有一个表视图,显示人员列表(属性:名字、姓氏)。表视图依赖NSFetchResultController来显示人员列表 我遵循嵌套上下文模式,如下所示: 根上下文(NSPrivateQueueConcurrencyType)主上下文(NSMainQueueConcurrencyType)子上下文(NSPrivateQueueConcurrencyType) 子上下文用于执行巨大的插入/获取(使用perormBlock:method)。 当我尝试执行一个巨大的插入(大约5000行),先保存子上下文,然后保存主上下文,再保存根上下文时,我看到我的UI被阻塞,直到保存完成 有谁能告诉我,为了实现高性能的应用程序,最好的解决方案是什么?谁能给我提供一个简单的代码,演示如何在后台进行大量的获取/插入,而不阻塞UIMultithreading 核心数据多线程和嵌套上下文,multithreading,core-data,nsmanagedobjectcontext,nsfetchedresultscontroller,Multithreading,Core Data,Nsmanagedobjectcontext,Nsfetchedresultscontroller,我刚刚开始学习核心数据编程。我尝试制作一个示例,其中有一个表视图,显示人员列表(属性:名字、姓氏)。表视图依赖NSFetchResultController来显示人员列表 我遵循嵌套上下文模式,如下所示: 根上下文(NSPrivateQueueConcurrencyType)主上下文(NSMainQueueConcurrencyType)子上下文(NSPrivateQueueConcurrencyType) 子上下文用于执行巨大的插入/获取(使用perormBlock:method)。 当我尝试
[_indicator startAnimating];
NSManagedObjectContext *aContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
aContext.parentContext = [[SDCoreDataController sharedInstance] mainManagedObjectContext];
[aContext performBlock:^{
NSError *error;
for (int i = 0; i < 5000; i++)
{
FootBallCoach *backgroundCoach = [NSEntityDescription insertNewObjectForEntityForName:@"FootBallCoach" inManagedObjectContext:aContext];
backgroundCoach.firstName = [NSString stringWithFormat:@"José %i",i];
backgroundCoach.lastName = [NSString stringWithFormat:@"Morinho %i",i];
backgroundCoach.cin = [NSString stringWithFormat:@"%i",i];
if (i % 50 == 0)
{
[aContext save:&error];
[aContext reset];
}
}
[[SDCoreDataController sharedInstance] saveMainContext];
[[SDCoreDataController sharedInstance] saveRootContext];
dispatch_async(dispatch_get_main_queue(), ^{
[_indicator stopAnimating];
[self refreshCoaches:nil];
});
}];
[\u指示器启动激活];
NSManagedObjectContext*aContext=[[NSManagedObjectContext alloc]initWithConcurrencyType:NSPrivateQueueConcurrencyType];
aContext.parentContext=[[SDCoreDataController sharedInstance]mainManagedObjectContext];
[A文本执行锁:^{
n错误*错误;
对于(int i=0;i<5000;i++)
{
FootBallCoach*backgroundCoach=[NSEntityDescription insertNewObjectForEntityForName:@“FootBallCoach”inManagedObjectContext:aContext];
backgroundCoach.firstName=[NSString stringWithFormat:@“José%i”,i];
backgroundCoach.lastName=[NSString stringWithFormat:@“Morinho%i”,i];
backgroundCoach.cin=[NSString stringWithFormat:@“%i”,i];
如果(i%50==0)
{
[文本保存:&错误];
[文本重置];
}
}
[[SDCoreDataController sharedInstance]saveMainContext];
[[SDCoreDataController sharedInstance]saveRootContext];
dispatch\u async(dispatch\u get\u main\u queue()^{
[_指示器停止动画制作];
[自我更新教练:无];
});
}];
不要进行“大量”导入。每次对存储执行写入操作时,
NSPersistentStoreCoordinator
都会锁定存储以执行任何其他类型的操作。因此,如果用户界面在此期间试图获取数据,它将被阻止。将保存的对象分割为100~200个对象(取决于对象大小和复杂性)。
分段实际上取决于对象图结构,伪代码是:
编辑:我编辑了代码,以反映对保存过程的更正。
您保存到存储区(实际文件)的操作也应该分段,否则您仍然会执行“巨大”的保存操作。
for ( i = 0; i < LARGE_N; i += BATCHSIZE)
{
@autoreleasepool {
batchInfo = importInfos[i : MIN(i+BATCHSIZE-1,LARGE_N-1]; //array of the batch
//use existing objects or create new ones if needed
//use batch fetching to reduce existing items find time
batchInfo = createOrReuseItemsForBatchInfo(batchInfo);
//you can also practice weeding:
// create all items as newly inserted
// after batch insertion completed, find existing items,
// replace them with the newly inserted and delete the duplicated inserted objects.
//save all the way to the store
NSManagedObjectContext* ctx = context;
__block BOOL saveSuccessful = YES;
while(ctx && saveSuccessful) {
[ctx performBlockAndWait:^{
saveSuccessful = [ctx save:&error]
}];
ctx = ctx.parentContext;
}
//handle unsuccessful save
[context reset];
//You can discard processed objects from importInfos array if you like
}
}
for(i=0;i
现在,我正在运行for循环,每次插入100个项目时都会保存。您确认嵌套上下文方法是最好的方法吗?当我的数据库第一次为空时,它可以正常工作。但是当我有大约20000个项目,并且我尝试插入5000个新项目时,UI会被阻止。如果保存100个项目,UI仍然会被阻止d尝试减少批处理大小。嵌套上下文体系结构在某些方面很好(根据我的经验,主要是小型导入和简单的存储操作)。如果您需要最大的并发性,您可以使用多协调器环境(但是您需要将更改合并到主上下文中,这本身就是一个故事).5K项插入总是很慢,因为写入操作会在操作系统级别阻止文件。正如我所说的,使用分段导入(最好在BG线程上花费更多时间并执行读取操作,然后太频繁和长时间地阻止UI)。我刚刚尝试了多协调器环境方法,得到了相同的结果。每次新的插入操作(5000项)我都会使用performBlock:方法创建一个单独的上下文,每次插入100项时我都会保存该方法。我的tableView(基于NSFetchResultController)仍处于阻塞状态。