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仍然被阻止,請嘗試減少批量大小。嵌套的上下文體系結構對於某些事情是有利的(根據我的經驗,大多數是小進口和簡單的存儲操作)。如果你需要最大的併發性,你可以使用多協調器環境(但是你需要將更改合併到你的主環境中,這是一個獨立的故事)。 –