Асинхронная выборка 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];
}
}
Ответы
Ответ 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:
или просто не включили его изначально?