CoreData Source Theme Update Has Random EXC_BAD_ACCESS KERN_INVALID_ADDRESS Error

I have a random mistake that tormented me for months that I just can't understand. I would say that it fails less than 1 time per 1000 times. I must have the CoreData configuration wrong, but I cannot figure it out or recreate it. The basic idea is that I get some information from the server and then update the CoreData object in the background thread. A CoreData object is not required immediately for the user interface.

All this is done in the DataService, which has a link to the NSManagedObjectContext that was originally created in AppDelegate. Note. Everything that references [DataService sharedService] uses AppDelegate.NSManagedObjectContext:

@interface DataService : NSObject {} @property (nonatomic,strong) NSManagedObjectContext* managedObjectContext; @end 

When the server returns with data, the updateProduct method is called:

 @implementation DataService + (NSManagedObjectContext*) newObjectContext { NSManagedObjectContext *context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; //step 1 AppDelegate* appDelegate = (AppDelegate*)[[UIApplication sharedApplication] delegate]; [context setPersistentStoreCoordinator:appDelegate.persistentStoreCoordinator]; [context setMergePolicy:NSMergeByPropertyObjectTrumpMergePolicy]; [appDelegate.managedObjectContext observeContext:context]; return context; } +(void) saveContext:(NSManagedObjectContext*) context { NSError *error = nil; if (context != nil) { if ([context hasChanges] && ![context save:&error]) { // Handle Error } } } +(void) updateProduct: (Product*) product { if(product == nil) return; //run in background dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, (unsigned long)NULL), ^(void){ //create private managed object NSManagedObjectContext *context = [DataService newObjectContext]; CoreDataProduct* coreProduct = [DataService product:product.productId withObjectContext:context]; if(product != nil) { //copy data over from product coreProduct.text = product.text; //ERROR HAPPENS HERE on save changes [DataService saveContext:context]; } //remove background context listening from main thread [DataService.managedObjectContext stopObservingContext:context]; }); } @end 

I use a generic NSManagedObjectContext + Helper.h category file that floats around GitHub and my EXC_BAD_ACCESS KERN_INVALID_ADDRESS error occurs in the [DataService.managedObjectContext mergeChangesFromNotification: (NSNotification *)) method that calls this

 @implementation NSManagedObjectContext (Helper) - (void) mergeChangesFromNotification:(NSNotification *)notification { //ERROR HAPPENS HERE [self mergeChangesFromContextDidSaveNotification:notification]; } @end 

I can’t understand why the mergeChangesFromContextDidSaveNotification method works randomly. I think the error is due to the loss of the link to the original sharedObjectContext. Although, if that were the case, I would suggest that the error will be in the updateProduct method, and not in the category class.

I believe that the newObjectContext and stopObservingContext methods refer to a managed ObjectContext on a background thread from the main thread. Since I am creating a private managedObjectContext, do I even need to make the general context associated with the main thread accessible to the private context? If so, am I doing it wrong?

Thanks in advance for your help.

+6
source share
1 answer

It looks like a new NSManagedObjectContext was created in the background thread, the source / parent NSManagedObjectContext needed to be watched in the main thread. As soon as I changed the observContext function to observationContextOnMainThread, this CoreData problem seems to have disappeared. I hope this helps someone.

Here is my updated method:

 + (NSManagedObjectContext*) newObjectContext { NSManagedObjectContext *context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; //step 1 AppDelegate* appDelegate = (AppDelegate*)[[UIApplication sharedApplication] delegate]; [context setPersistentStoreCoordinator:appDelegate.persistentStoreCoordinator]; [context setMergePolicy:NSMergeByPropertyObjectTrumpMergePolicy]; [appDelegate.managedObjectContext observeContextOnMainThread:context]; return context; } 
+4
source

Source: https://habr.com/ru/post/972220/


All Articles