Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
430 views
in Technique[技术] by (71.8m points)

ios - CoreData asynchronous fetch causes concurrency debugger error

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.

It says the fetch has been enqueued from the main thread, but it seems to actually happen on another.

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];
    }
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...