Подтвердить что ты не робот

Асинхронная выборка CoreData вызывает concurrency ошибку отладчика

Я использую

-com.apple.CoreData.ConcurrencyDebug

для запуска отладки concurrency в моем приложении CoreData.

Во время запуска приложения я выполняю асинхронную выборку в контексте объекта с управляемым потоком.

// set up the async request
   NSError * error = nil;
        [MOC executeRequest:asyncFetch error:&error];
        if (error) {
            NSLog(@"Unable to execute fetch request.");
            NSLog(@"%@, %@", error, error.localizedDescription);
        }

Этот код вызывается из основного потока, но executeRequest: помещает его в другой поток, который, как я понимаю, является правильным поведением.

Отладчик concurrency не нравится, говоря (я считаю), что я делаю что-то неправильно здесь. Я также попытался обернуть это в [MOC performBlock:], который также работает, но также вызывает нарушение многопоточности. В обоих случаях я получаю следующее:

[NSManagedObjectContext __Multithreading_Violation_AllThatIsLeftToUsIsHonor__

Я неправильно использую асинхронные выборки или отладчик concurrency здесь неправильно?

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

Он говорит, что выборка была выделена из основного потока, но, похоже, это происходит на другом.

EDIT: здесь запрос на выборку:

 NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"MyEntity"];

 NSPredicate * pred = [NSPredicate predicateWithFormat:@"boolProperty == YES"];
    fetchRequest.predicate = pred;
 NSSortDescriptor * sort = [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES];
 fetchRequest.sortDescriptors = @[sort];      fetchRequest.propertiesToFetch = @[@"prop1", @"prop2", @"prop3", @"prop4"];

 NSPersistentStoreAsynchronousFetchResultCompletionBlock resultBlock = ^(NSAsynchronousFetchResult *result) {
        dispatch_async(dispatch_get_main_queue(), ^{
            [[NSNotificationCenter defaultCenter] postNotificationName:kFetchCompleteNotification object:result];
        });
    };

 NSAsynchronousFetchRequest *asyncFetch = [[NSAsynchronousFetchRequest alloc]
                                              initWithFetchRequest:fetchRequest
                                              completionBlock:resultBlock];

Затем я получаю результаты извещения:

- (void)fetchCompletedNote:(NSNotification *)note {
    NSAsynchronousFetchResult * result = note.object;
    if (![cachedResults isEqualToArray:result.finalResult]){
        cacheResults = result.finalResult;
        [self.collectionView reloadData];
    }
}
4b9b3361

Ответ 1

Я думаю, что это ошибка Apple.

Я подал сообщение об ошибке: https://openradar.appspot.com/30692722

и добавлен примерный проект, который воспроизводит проблему: https://github.com/jcavar/examples/tree/master/TestAsyncFetchCoreData

Кроме того, если вы не хотите отключать флаг только из-за этой проблемы, вы можете попробовать swizzle __Multithreading_Violation_AllThatIsLeftToUsIsHonor__ метод на NSManagedObjectContext только для этой части кода. Вам необходимо вернуть это после выполнения запроса, чтобы вы получили нарушения для реальных проблем.

Ответ 2

Отладчик concurrency сообщает вам, что вы обращаетесь к MOC из неправильного потока/очереди. Вы можете вызывать только -executeRequest: error: в потоке/очереди, к которой принадлежит контекст. Если это NSMainQueueConcurrencyType, вам нужно быть в основном потоке. В противном случае, если это NSPrivateQueueConcurrencyType, вам нужно использовать -performBlock: или -performBlockAndWait: для запуска выполнения в правильной очереди.

Я добавил скриншот, см. выше. Запрос помещается в очередь из основного потока, но выполняется другим.

Хорошо, пару вещей:

  • Это строка, которая разбивается/сбой или вы видите ошибку?
  • Неверная обработка ошибок. Вы должны смотреть на результат -executeRequest: error:, и если результат nil, то вы находитесь в состоянии ошибки. Переменная ошибки может быть заполнена даже с успехом.

Я отмечаю, что код, который вы опубликовали на скриншоте, отличается от кода, который вы опубликовали ранее. Вы добавили -performBlock: или просто не включили его изначально?