8

My iOS app uses core data via multiple threads. I am getting some crash reports with the following message: "'NSObjectInaccessibleException', reason: 'CoreData could not fulfill a fault for '0x1e07a9b0 ''

I understand what is causing this problem - that the object was deleted but another thread is trying to access it. I am working to solve the problem but I want to add a check in the background thread to see if the object will fault in this manner.

My code at the moment relates to myObject.myValue. Is it possible to do some check, such as:

if (!myObject.myValue) {
    return;
}

... so that it will get out of the method before doing anything that could cause such a crash? Or will simply calling myObject.myValue, even to see if it's null, cause such an exception to be thrown?

Charles
  • 50,943
  • 13
  • 104
  • 142
Jason
  • 14,517
  • 25
  • 92
  • 153
  • 8
    By the way, you have an extremely low answer acceptance which is probably why no one wants to respond to your questions. Please consider reviewing your old questions and selecting the correct answer for each. http://stackoverflow.com/users/353137/jason?tab=questions – iwasrobbed Mar 12 '13 at 13:00

5 Answers5

19

You could try and use existingObjectWithID:error::

Returns the object for the specified ID.

   - (NSManagedObject *)existingObjectWithID:(NSManagedObjectID *)objectID error:(NSError **)error

Discussion

If there is a managed object with the given ID already registered in the context, that object is returned directly; otherwise the corresponding object is faulted into the context.

This method might perform I/O if the data is uncached.

Unlike objectWithID:, this method never returns a fault.

You could dO:

if ([myMOC existingObjectWithID:myObject.objectID error:&error])
    ...
Community
  • 1
  • 1
sergio
  • 68,819
  • 11
  • 102
  • 123
5

You should verify that the object exists before accessing it's variables if you're having issues where the object may be deleted on another thread.

Two methods:

  1. Refresh the view datasources whenever your data is being deleted. You can do this by registering for the NSManagedObjectContextObjectsDidChangeNotification notification and then parsing the userInfo on that notification to see which object was deleted.
  2. Use code similar to below when you're passing data around to multiple threads.

Example:

// Cache and pass the object's ID off to another thread to do work on
// You can just store it as a property on the class
@try {
    NSManagedObject *theObject = [managedObjectContext objectWithID:self.theObjectID];

    // do stuff with object
}
@catch (NSException * e) {
    // An entity with that object ID could not be found (maybe they were deleted)
    NSLog(@"Error finding object: %@: %@", [e name], [e reason]);
}
iwasrobbed
  • 46,496
  • 21
  • 150
  • 195
  • Method #1, definitely. I can wait for notifications on my "detail" view (accessible before/during a synchronization) and disable any functionality that interacts with the object, notify the user, etc. – Mark Aug 19 '13 at 16:50
3

You can check the NSManagedContext is existed when you use the NSManagedObject. like this:

if (obj.managedObjectContext)
{
    //do things
}
cleexiang
  • 149
  • 2
  • 7
  • 1
    I had the same thought, however I can't find any documentation confirming this behavior. Can anyone confirm, that this is a definitive way to check if the object is still available? – Daniel Rinser Sep 22 '15 at 14:39
0

You can check [myObject isFault] where myObject is a NSManagedObject instance

Mert Buran
  • 2,989
  • 2
  • 22
  • 34
  • The fact that an object is a fault alone does not mean that accessing any of its properties will throw this exception. Usually, this will just cause the data to be loaded from the data store. The exception is only thrown if this object doesn't exist anymore in the data store and thus can't be loaded (a.k.a. "faulted"). – Daniel Rinser Sep 22 '15 at 14:37
0

You could give a try to use :

shouldDeleteInaccessibleFaults

property on managed object context. As this article says it should change the behaviour of faulting already deleted object.

https://cocoacasts.com/what-are-core-data-query-generations/

Edit: Since iOS 9 (when it was added) this property default value is YES.