Yozone W.
Yozone W.

Reputation: 303

CoreData could not fulfill a fault with unmodified relationship

I have a entity A, it has a relationship B.

Here is a array fetched from CoreData:

NSPredicate * predicate = [NSPredicate predicateWithFormat:@"isSynchronized = NO"];
NSManagedObjectContext *context = [NSManagedObjectContext MR_contextForCurrentThread];
NSArray * newWordsToSynchronize = [A MR_findAllWithPredicate:predicate inContext:context];
NSMutableArray * newWordsParameters = [NSMutableArray arrayWithCapacity:[asToSynchronize count]];
[newWordsToSynchronize enumerateObjectsUsingBlock:^(A * a, NSUInteger idx, BOOL * stop) {
    NSLog(@"============= may have some problem ============");
    NSLog(@"[a hasFaultForRelationshipNamed:@\"b\"] = %d", [a hasFaultForRelationshipNamed:@"b"]);
    NSLog(@"a.word = %@", a.word);
    NSLog(@"a.b.objectID = %@", a.b.objectID);
    NSLog(@"a.managedObjectContext = %@", a.managedObjectContext);
    NSLog(@"a.b.managedObjectContext = %@", [a.b managedObjectContext]);
    NSLog(@"a.b.managedObjectContext = %@", [a.b managedObjectContext]);
    NSLog(@"a.managedObjectContext = %@", a.managedObjectContext);
    NSDictionary *paramDictionary = @{
            @"nbook" : a.b.name,
            @"lang" : a.lang,
            ...
    };
    [newWordsParameters addObject:paramDictionary];
}];

The [a.b managedObjectContext] method may return nil when I call it at second time and then the app goes crash.

Crash log from console:

2014-01-20 14:29:14.561 MyApp[10563:2e07] a.b.objectID = 0x1754e940 <x-coredata://DFC4F956-D5AC-4264-8717-C07090CA9547/B/p1>
2014-01-20 14:29:14.561 MyApp[10563:2e07] a.managedObjectContext = <NSManagedObjectContext: 0x1754bc00>
2014-01-20 14:29:14.561 MyApp[10563:2e07] a.b.managedObjectContext = <NSManagedObjectContext: 0x1754bc00>
2014-01-20 14:29:14.562 MyApp[10563:2e07] a.b.managedObjectContext = (null)
*** Terminating app due to uncaught exception 'NSObjectInaccessibleException', reason: 'CoreData could not fulfill a fault for '0x1754e940 <x-coredata://DFC4F956-D5AC-4264-8717-C07090CA9547/B/p1>''
*** First throw call stack:
(
    0   CoreFoundation                      0x037495e4 __exceptionPreprocess + 180
    1   libobjc.A.dylib                     0x034cc8b6 objc_exception_throw + 44
    2   CoreData                            0x031a233b _PFFaultHandlerLookupRow + 2715
    3   CoreData                            0x031a1897 -[NSFaultHandler fulfillFault:withContext:forIndex:] + 39
    4   CoreData                            0x031a1473 _PF_FulfillDeferredFault + 259
    5   CoreData                            0x031a12c6 _sharedIMPL_pvfk_core + 70
    6   CoreData                            0x031e7130 _pvfk_5 + 32
    7   MyApp                        0x00181b00 __68-[CichangAHTTPEngine synchronizeAsOnCompletion:failure:]_block_invoke + 1760
    8   CoreFoundation                      0x037435eb __NSArrayEnumerate + 571
    9   CoreFoundation                      0x03743196 -[NSArray enumerateObjectsWithOptions:usingBlock:] + 102
    10  CoreFoundation                      0x037430a5 -[NSArray enumerateObjectsUsingBlock:] + 53
    11  MyApp                        0x0018105b -[CichangAHTTPEngine synchronizeAsOnCompletion:failure:] + 1179
    12  MyApp                        0x00185d9e __65-[CichangAHTTPEngine downloader:didFinishedDownloadObject:]_block_invoke_3 + 2030
    13  libdispatch.dylib                   0x040717f8 _dispatch_call_block_and_release + 15
    14  libdispatch.dylib                   0x040864b0 _dispatch_client_callout + 14
    15  libdispatch.dylib                   0x04074eeb _dispatch_root_queue_drain + 287
    16  libdispatch.dylib                   0x04075137 _dispatch_worker_thread2 + 39
    17  libsystem_pthread.dylib             0x04412dab _pthread_wqthread + 336
    18  libsystem_pthread.dylib             0x04416cce start_wqthread + 30
)
libc++abi.dylib: terminating with uncaught exception of type _NSCoreDataException

I found that B will be deallocated after first [a.b managedObjectContext] calling.

I think it was mainly caused by Core Data 1550 error (If I do not call [a.b managedObjectContext], Core Data will reports "The operation couldn’t be completed. (Cocoa error 1550.)"). But what may cause 1550 error and how to fix it?

1550 error report:

Error Domain=NSCocoaErrorDomain Code=1550 "The operation couldn’t be completed. (Cocoa error 1550.)" UserInfo=0x167269c0 {NSLocalizedDescription=The operation couldn’t be completed. (Cocoa error 1550.), Dangling reference to an invalid object.=null, NSValidationErrorObject=<A: 0x16bab420> (entity: A; id: 0x16baae50 <x-coredata://A85EE9AB-97C1-43C1-B92E-A6C906F0C1A8/A/p168> ; data: {
    date = "2014-01-21 02:32:00 +0000";
    expect = "2014-01-21 02:31:59 +0000";
    isSynchronized = 1;
    lang = en;
    last = "2014-01-21 02:01:59 +0000";
    level = 1;
    b = "0x16bab460 <x-coredata://A85EE9AB-97C1-43C1-B92E-A6C906F0C1A8/B/p1>";
    status = "-1";
    studycount = 0;
    trans = "v. \U6d4b\U91cf\Uff0c\U6743\U8861 ";
    word = measure;
}), NSAffectedObjectsErrorKey=(
    "<B: 0x16babd70> (entity: B; id: 0x16bab460 <x-coredata://A85EE9AB-97C1-43C1-B92E-A6C906F0C1A8/B/p1> ; data: <fault>)"
), NSValidationErrorKey=newWordBook, NSValidationErrorValue=<B: 0x16babd70> (entity: B; id: 0x16bab460 <x-coredata://A85EE9AB-97C1-43C1-B92E-A6C906F0C1A8/B/p1> ; data: <fault>), NSValidationErrorShouldAttemptRecoveryKey=true}

If the 1550 error happened, "CoreData could not fulfill a fault" crash will more easer to cause.

Upvotes: 0

Views: 2039

Answers (1)

eofster
eofster

Reputation: 2047

“Core Data could not fulfill fault” really means that there was a deletion. There was data in the persistent store. Then managed object representing this data was created. The object was a fault. Then the data in the store was deleted. Then some property of an object was accessed and Core Data tried to fulfill the fault, but couldn’t.

If you’re not doing explicit deletions, then also make sure that implicit deletions are not happening. Deletion behind the scenes could happen when one of your relationships was configured with the cascade deletion rule.

In your example this could happen if the relationship from A to B was configured with cascade rule, and object A was deleted.

Upvotes: 2

Related Questions