1

Я пытаюсь создать несколько методов, которые упрощают выполнение данных Core Data в фоновом режиме. Что я делаю:Удаление в фоновом режиме не работает после запуска

  • Использование NSOperationQueue «s -addOperationWithBlock: создать фоновый поток
  • В фоновом потоке, создать NSManagedObjectContext с тем же persistentStoreCoordinator качестве контекста на главном потоке и с undoManager набором для nil
  • Добавить наблюдатель от центра уведомлений по умолчанию для прослушивания NSManagedObjectContextDidSaveNotification уведомлений и обращаться с ними так:

    - (void)mergeChanges:(NSNotification *)notification 
    { 
        dispatch_sync(dispatch_get_main_queue(), ^{ 
         [_mainContext mergeChangesFromContextDidSaveNotification:notification]; 
        }); 
    } 
    
  • Выполнение блока, который был передан и который выполняет все основные данные. Периодически он вызывает save: на фоне контекста

  • После того, как все сделано, удалить наблюдателя от центра уведомлений

Описанный метод можно найти ниже.

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

CoreData: error: Serious application error. An exception was caught from the delegate of NSFetchedResultsController during a call to -controllerDidChangeContent:. CoreData could not fulfill a fault for [...]

Как видно из ошибок, я использую NSFetchedResultsController для отображения данных. Кэш контроллера установлен в nil.

Любые предложения о том, как исправить это?


Вот соответствующий код. Обратите внимание, что я использую ARC.

FJCoreDataBackgroundBlock определяется следующим образом:

typedef void(^FJCoreDataBackgroundBlock)(NSManagedObjectContext *backgroundContext); 

Метод выполнить кучу материала сердечника данных в фоновом режиме

- (void)performBlockInBackground:(FJCoreDataBackgroundBlock)block 
{ 
    [FJSharedOperationQueue addOperationWithBlock:^{ 

     self.managedObjectContext = [[NSManagedObjectContext alloc] init]; 
     [_managedObjectContext setUndoManager:nil]; 
     [_managedObjectContext setPersistentStoreCoordinator:self.persistentStoreCoordinator]; 

     [self setupNotificationCenterObserverForContext:_managedObjectContext]; 

     FJCoreDataBackgroundBlock backgroundBlock = [block copy]; 
     backgroundBlock(self.managedObjectContext); 

     [self saveBackgroundContext]; 
     [self saveMainContext]; 
     [self removeNotificationCenterObserver]; 
    }]; 
} 

Реализация FJSharedOperationQueue:

+ (NSOperationQueue *)sharedQueue 
{ 
    static dispatch_once_t predicate = 0; 

    __strong static NSOperationQueue *_sharedQueue = nil; 

    dispatch_once(&predicate, ^{ 
     _sharedQueue = [[NSOperationQueue alloc] init]; 
     [_sharedQueue setMaxConcurrentOperationCount:1]; 
    }); 

    return _sharedQueue; 
} 

+ (void)addOperationWithBlock:(void (^)(void))block 
{ 
    [[FJSharedOperationQueue sharedQueue] addOperationWithBlock:block]; 
} 

ответ

0

сейчас это странно: я перетасовывал строки кода в блоке t hat удаляет объекты. Перед тем как это выглядело так:

FJCoreDataHelper *helper = [[FJCoreDataHelper alloc] initUsingMainManagedObjectContext:[self mainContext]]; 

[helper performBlockInBackground:^(NSManagedObjectContext *backgroundContext) { 

    // [Fetch objets here...] 

    // Delete: 

    const int kSaveThreshold = 50; 
    for (int card = 0, count = [allCards count]; card < count; card++) 
    { 
     [backgroundContext deleteObject:[allCards objectAtIndex:card]]; 

     if (card % kSaveThreshold == 0) 
     { 
      [helper saveBackgroundContext]; 
     } 
    } 
    }]; 

Чтобы исправить это, я просто должен был сохранить основной контекст после сохранения фона контекста:

[helper performBlockInBackground:^(NSManagedObjectContext *backgroundContext) { 

    // [Fetch objets here...] 

    // Delete: 

    const int kSaveThreshold = 50; 
    for (int card = 0, count = [allCards count]; card < count; card++) 
    { 
     [backgroundContext deleteObject:[allCards objectAtIndex:card]]; 

     if (card % kSaveThreshold == 0) 
     { 
      [helper saveBackgroundContext]; 
      [helper saveMainContext]; 
     } 
    } 
    }]; 

Если я сохраняю только фоновый контекст, он выходит из строя. Если сначала сохранить основной контекст, он также сработает. Я нахожу это странным, потому что я думал, что объединение фонового контекста в основной контекст также сохранит основной контекст ...

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