"Core Data could not fulfill a fault.." error

12,061

This is an old question, I have struggled resolving this for some time now. So, thought it would be best to document it.

As Weichsel above mentioned, the Apple documentation rightly points out reason for this exception. But it is a hectic job to identify the module due to which the NSManagedObject subclass' object is being retained (if 1st cited reason in the documentation is the root cause of the problem).

So, I started out by identifying the parts of my code which was retaining the NSManagedObject, instead I retained the NSManagedObjectID and create the managed object out of it whenever needed. The discussion in similar lines can be found in Restkit documentation:

  1. https://github.com/RestKit/RestKit/commit/170060549f44ee5a822ac3e93668dad3b396dc39
  2. https://github.com/RestKit/RestKit/issues/611#issuecomment-4858605

Updated my setter and getter so that the interface with rest of the modules remain same while internally we now depend upon NSManagedObjectID and avoid retaining of NSManageObject:

-(CSTaskAbstract*)task
{
    CSTaskAbstract *theTask = nil;
    if (self.taskObjectID)
    {
        NSManagedObjectContext *moc = [(CSAppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
        // https://github.com/RestKit/RestKit/commit/170060549f44ee5a822ac3e93668dad3b396dc39 &
        // https://github.com/RestKit/RestKit/issues/611#issuecomment-4858605
        NSError *theError = nil;
        NSManagedObject *theObject = [moc existingObjectWithID:self.taskObjectID
                                                         error:&theError];
        if ([theObject isKindOfClass:[CSTaskAbstract class]])
        {
            theTask = (CSTaskAbstract*)theObject;
        }
    }
    return theTask;
}
-(void)setTask:(CSTaskAbstract *)inTask
{
    if (inTask!=self.task)
    {
        // Consequences of retaining a MO when it is detached from its MOC
        [self setTaskObjectID:[inTask objectID]];
    }
}

The above is the first half of the problem solved. We need to find out dependency in suspicious parts of our app and eliminate.

There was some other problem too, instruments -> allocations is a good source to find out which modules are actually retaining the managed objects, the exception object would have details about which managed object is creating the problem, filter results for that object as shown below:

Instruments - Allocations

We were performing KVO on a managed object. KVO retains the observed managed object and hence the exception is thrown and it's back trace would not be from within our project. These are very hard to debug but guess work and tracking the object's allocation and retain-release cycle will surely help. I removed the KVO observation part and it all started working.

Share:
12,061
MobX
Author by

MobX

Updated on June 17, 2022

Comments

  • MobX
    MobX almost 2 years

    I am developing an application in cocoa. I am facing a critical problem.

    I am deleting entries of an object named "Directory" in Core Data using the following code:

    NSEnumerator *tempDirectories = [[folderArrayController arrangedObjects] objectEnumerator];
    id tempDirectory;
    while (tempDirectory = [tempDirectories nextObject]){
        [managedObjectContext deleteObject:tempDirectory];
    }
    

    But sometimes an exception like "Core Data could not fulfill a fault.." occurs while trying to save after deletion. I am using the code [managedObjectContext save];

    I am new in Core Data... Looking forward to a solution.