Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make NSManagedObject not fault?

I'm currently debugging a big project written by another developer. The project uses CoreData which i am very new to. I'm having a crash which happens due to the fact that some NSManagedObject is being a fault(i have poor understanding of what fault is) and i would like to convert the object into "not fault" and see if it helps. Reading documentation made me think that to make object not fault is equal to to fire fault (again i have poor understanding of what is "to fire"), so i decided to fire it by calling any method on it, and this method is hasChanges since it's not in the list of methods which don't fire fault. However even after calling this method the object still remained being fault. Can anyone give me an example of how to convert NSManagedObject into "not fault" state?

like image 220
Andrey Chernukha Avatar asked Feb 15 '23 13:02

Andrey Chernukha


2 Answers

The exception you mentioned in a comment is:

Terminating app due to uncaught exception 'NSObjectInaccessibleException', reason: 'CoreData could not fulfill a fault for '0x1f0627a0 <x-coredata://E40418A0-A8E5-4340-865F-A9DA2E0095DD/CoreObject/p288>''

The "could not fulfill a fault" message indicates that this is not simply a problem with firing the fault. In fact there are no special steps to fire a fault-- you just access the attributes, and if necessary, the fault fires automatically.

What this error is telling you is that you're doing something that causes a fault to fire, but that Core Data can't find any record of the instance you're using. This can happen in certain scenarios, for example:

  1. Fetch an object, and leave it as a fault (i.e. don't access any attributes)
  2. Delete it from Core Data, but keep a reference to the object (maybe in an instance variable)
  3. Save changes
  4. Try to access an attribute on the object you fetched in step 1.

At this point Core Data would normally use the object to look up the attribute value. But you already deleted it, so the attribute data is gone. Core Data throws this exception.

There are some other scenarios that can trigger this-- calling reset on a managed object context while keeping previously fetched objects around, or removing the persistent store (so that the data still exists in the store file, but the file isn't loaded anymore). In general it means Core Data is trying to look up data on an object that's no longer valid.

What you need to do:

  • Figure out which object is causing this. Setting an exception breakpoint, so that the debugger loads just as the crash is happening, is probably a good idea.
  • Get rid of that object. Preventing the fault from firing might prevent this specific crash, but as long as you still have this object, it's like a land mine in your app. It will explode and crash the app as soon as you touch it.
  • Figure out why you have invalid managed objects lurking in memory. Maybe you should have gotten rid of them earlier? Maybe you're accidentally deleting something you don't want to delete? For some reason you're keeping managed objects around when they're no longer valid. This is the core problem that's causing your trouble.
like image 144
Tom Harrington Avatar answered Feb 24 '23 09:02

Tom Harrington


Faulting is the process whereby an object and/or its properties are fetched from the database on-demand.

For example, if you attempt to access a property or relation on some object, person.name, that object may not have its data in-memory, and it has to be fetched from the underlying data store. This is a fault.

Faulting is a normal part of how Core Data works, and should not be related to crashes. An object will be unfaulted when you try to access its properties and relations.

like image 43
Mike Weller Avatar answered Feb 24 '23 10:02

Mike Weller