0

我刚开始学习核心数据编程。我试图做一个例子,其中有一个显示人员列表(属性:名字,姓氏)的表视图。表视图依赖于NSFetchResultController来显示人员列表。核心数据多线程和嵌套上下文

我跟着嵌套上下文图案如下:

根上下文(NSPrivateQueueConcurrencyType)< --->主上下文(NSMainQueueConcurrencyType)< --->儿童上下文(NSPrivateQueueConcurrencyType)。

子上下文用于执行巨大的插入/获取(使用perormBlock:方法)。 当我尝试执行一个巨大的插入(约5000行)时,保存子上下文,然后保存主上下文,然后根上下文,我看到我的用户界面被阻止,直到保存完成。

任何人都可以告诉我为了创建高性能应用程序,采用何种最佳解决方案?任何人都可以请我提供一个很好的简单代码,展示如何在不阻止用户界面的情况下在后台进行巨大的读取/插入操作?

[_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

https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/CoreData/Concurrency.html –

回答

1

不要做“巨大的”进口。
每次对存储进行写操作时,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 
    } 
} 
+0

那么现在我是循环运行,每次我插入100项节能。你确认嵌套的上下文方法是最好的吗? – rokridi

+0

当首先我的数据库为空时,它工作正常。但是,当我有大约20 000个项目,我尝试插入5000个新项目时,用户界面被阻止。 – rokridi

+0

如果您保存了100个项目,并且UI仍然被阻止,请尝试减少批量大小。嵌套的上下文体系结构对于某些事情是有利的(根据我的经验,大多数是小进口和简单的存储操作)。如果你需要最大的并发性,你可以使用多协调器环境(但是你需要将更改合并到你的主环境中,这是一个独立的故事)。 –