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 объектов (в зависимости от размера и сложности объекта).
Сегментация действительно зависит от структуры графа объекта, псевдокод будет:

Edit: Я редактировал код, чтобы отразить корректировку к процессу сохранения.
Ваше сохранение в магазине (фактический файл) также должно быть сегментировано, иначе вы все равно получите «огромную» операцию сохранения.

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 элементов, а пользовательский интерфейс по-прежнему заблокирован, попробуйте уменьшить размер партии. Вложенная контекстная архитектура хороша для некоторых вещей (в основном небольших импортных операций и простых операций хранилища из моего опыта). Если вам нужен максимальный параллелизм, вы можете использовать среду с несколькими координаторами (но тогда вам нужно будет объединить изменения в свой основной контекст, который является историей сам по себе). –

Смежные вопросы