Hi my app is crashing when the managed object is changed in one child context(saved after) and deleted in other child context(saved first).
How to reproduce:
1.Create new project with 'Empty Application' template and core data enabled.
2.Change the managedObjectContext getter to following (i have changed the concurrency type)
- (NSManagedObjectContext *)managedObjectContext
{
if (_managedObjectContext != nil) {
return _managedObjectContext;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil) {
_managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
[_managedObjectContext setPersistentStoreCoordinator:coordinator];
}
return _managedObjectContext;
}
3.Please replace didfinishLaunching method to following
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
{
//insert
NSManagedObjectContext *insertingContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[insertingContext setParentContext:self.managedObjectContext];
[insertingContext performBlockAndWait:^{
Test *test = (Test *)[NSEntityDescription insertNewObjectForEntityForName:@"Test" inManagedObjectContext:insertingContext];
test.test=@"test";
[insertingContext save:nil];
[self.managedObjectContext performBlockAndWait:^{
[self.managedObjectContext save:nil];
}];
NSLog(@"inserted and saved to persistance store");
}];
}
{
//get the mo and change the property
NSManagedObjectContext *acceesingContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
{
[acceesingContext setParentContext:self.managedObjectContext];
[acceesingContext performBlockAndWait:^{
NSFetchRequest *request = [[NSFetchRequest alloc] init] ;
[request setEntity:[NSEntityDescription entityForName:@"Test" inManagedObjectContext:acceesingContext]];
NSArray *results = [acceesingContext executeFetchRequest:request error:nil];
if ([results count] > 0 )
{
Test *test= [results objectAtIndex:0];
test.test=@"Hello";
NSLog(@"accessed and changed the property so that fault is fired");
}
}];
}
{
NSManagedObjectContext *deletingContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[deletingContext setParentContext:self.managedObjectContext];
[deletingContext performBlockAndWait:^{
NSFetchRequest *request = [[NSFetchRequest alloc] init] ;
[request setEntity:[NSEntityDescription entityForName:@"Test" inManagedObjectContext:deletingContext]];
NSArray *results = [deletingContext executeFetchRequest:request error:nil];
if ([results count] > 0 )
{
Test *test= [results objectAtIndex:0];
[deletingContext deleteObject:test];
[deletingContext save:nil];
[self.managedObjectContext performBlockAndWait:^{
[self.managedObjectContext save:nil];
}];
NSLog(@"deleted and saved to persistance store");
}
}];
}
[acceesingContext performBlock:^{
// it is crashing here, please help.
[acceesingContext save:nil];
}];
}
return YES;
}
4.Finally Add Entity named 'Test' with an attribute 'test' (NSString) and run the app
Problem what i am facing is, when one child moc has fetched a managed object and changed a property in it, while other child deletes and save the changes to persistent store. the crash occurs while saving the moc which has modified the mo.
Crash Report
*** Terminating app due to uncaught exception 'NSObjectInaccessibleException', reason: 'CoreData could not fulfill a fault for '0xd0000000001c0000 ''
*** First throw call stack:
(
0 CoreFoundation 0x0000000101bf0795 __exceptionPreprocess + 165
1 libobjc.A.dylib 0x0000000101953991 objc_exception_throw + 43
2 CoreData 0x0000000100278a93 _PFFaultHandlerLookupRow + 1075
3 CoreData 0x00000001003063a3 -[NSManagedObject(_NSInternalMethods) _updateFromRefreshSnapshot:includingTransients:] + 243
4 CoreData 0x00000001002aa563 -[NSManagedObjectContext(_NestedContextSupport) _copyChildObject:toParentObject:fromChildContext:] + 771
5 CoreData 0x00000001002aa01b -[NSManagedObjectContext(_NestedContextSupport) _parentProcessSaveRequest:inContext:error:] + 1019
6 CoreData 0x0000000100310243 __82-[NSManagedObjectContext(_NestedContextSupport) executeRequest:withContext:error:]_block_invoke + 563
7 libdispatch.dylib 0x0000000101fc205a _dispatch_barrier_sync_f_slow_invoke + 45
8 libdispatch.dylib 0x0000000101fd16fd _dispatch_client_callout + 8
9 libdispatch.dylib 0x0000000101fc146c _dispatch_main_queue_callback_4CF + 354
10 CoreFoundation 0x0000000101c4e729 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 9
11 CoreFoundation 0x0000000101b9b9a4 __CFRunLoopRun + 1764
12 CoreFoundation 0x0000000101b9aed3 CFRunLoopRunSpecific + 467
13 GraphicsServices 0x0000000103b893a4 GSEventRunModal + 161
14 UIKit 0x00000001005bba63 UIApplicationMain + 1010
15 TestCrash 0x00000001000040a3 main + 115
16 libdyld.dylib 0x000000010227e7e1 start + 0
17 ??? 0x0000000000000001 0x0 + 1
)
libc++abi.dylib: terminating with uncaught exception of type _NSCoreDataException