CoreData asynchronous fetch causes concurrency debugger error

匿名 (未验证) 提交于 2019-12-03 03:04:01

问题:

I'm using the

-com.apple.CoreData.ConcurrencyDebug 

argument on launch to debug concurrency in my CoreData app.

During app launch, I perform an asynchronous fetch on the main thread's managed object context.

// 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);         } 

This code is called from the main thread, but executeRequest: enqueues it to another thread, which I understand to be the correct behavior.

The concurrency debugger doesn't like this, saying (I reckon) that I'm doing something wrong here. I've also tried wrapping this in [MOC performBlock:] which also works, but also causes a multithreading violation. In both cases I get this :

[NSManagedObjectContext __Multithreading_Violation_AllThatIsLeftToUsIsHonor__ 

Am I using async fetches incorrectly, or is the concurrency debugger wrong here?

EDIT : I've also tried wrapping it in MOC performBlock which should ensure that it gets called from the main thread. In any case, the call is enqueued from the main thread, but executed elsewhere.

EDIT : here's the fetch request:

 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]; 

Then I receive the results from the notification:

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

回答1:

I think this is Apple's bug.

I filed bug report: https://openradar.appspot.com/30692722

and added example project that reproduces issue: https://github.com/jcavar/examples/tree/master/TestAsyncFetchCoreData

Also, if you don't want to disable flag just because of this issue you may want to swizzle __Multithreading_Violation_AllThatIsLeftToUsIsHonor__ method on NSManagedObjectContext just for this part of code. You need to revert that after request is executed so you get violations for real issues.



回答2:

The concurrency debugger is telling you that you are accessing MOC from the wrong thread/queue. You can only call -executeRequest: error: on the thread/queue that the context belongs to. If this is a NSMainQueueConcurrencyType then you need to be on the main thread. Otherwise, if it is a NSPrivateQueueConcurrencyType you need to use either -performBlock: or -performBlockAndWait: to run the execute on the correct queue.

I added a screenshot, see above. The request is enqueued from the main thread, but executed on another.

Ok, a couple of things:

  1. Is that the line that is breaking/crashing or are you seeing the error output?
  2. Your error handling is incorrect. You should be looking at the result of the -executeRequest: error: and if the result is nil then you are in an error state. The error variable can be populated even with a success.

I note that the code you posted in your screenshot is different than the code you posted previously. Did you add the -performBlock: or just not include it originally?



易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!