Reputation: 303
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
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