我刚开始学习核心数据编程。我试图做一个例子,其中有一个表格视图,显示人员列表(属性:名字,姓氏)。表视图依赖于NSFetchResultController来显示人员列表。
我按照以下方式遵循嵌套的上下文模式:
Root Context(NSPrivateQueueConcurrencyType)< --->主要上下文(NSMainQueueConcurrencyType)< --->儿童上下文(NSPrivateQueueConcurrencyType)。
子上下文用于执行大量插入/获取(使用perormBlock:方法)。 当我尝试执行大量插入(大约5000行)时,保存子上下文然后保存主上下文然后保存根上下文,我看到我的UI被阻止,直到保存完成。
请问任何人请告诉我采用高性能应用程序的最佳解决方案是什么?任何人都可以请给我一个很好的简单代码,展示如何在不阻塞UI的情况下在后台进行大量的获取/插入?
[_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];
});
}];
答案 0 :(得分:1)
不要做“巨大”的进口
每次对商店执行写入操作时,NSPersistentStoreCoordinator
都会锁定商店以进行任何其他类型的操作。因此,如果您的UI在此期间尝试获取数据,则会被阻止。
将您的保存分为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
}
}