核心数据多线程和嵌套上下文

时间:2013-11-26 11:06:42

标签: multithreading core-data nsmanagedobjectcontext nsfetchedresultscontroller

我刚开始学习核心数据编程。我试图做一个例子,其中有一个表格视图,显示人员列表(属性:名字,姓氏)。表视图依赖于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];
    });

}];

1 个答案:

答案 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
    }
}