Search code examples
core-datansmanagedobjectobjective-c-2.0

CoreData. Successfully saving an invalid objects


I have property(as managedObject) in a singleton. This object in property may be updated(removed, then created new object with custom Id, equal with Id of old object), then I save context, nullify the property, fetch new object and assign this to property.

I didn't have an error, all normally. After restarting application I got "CoreData could not fulfill a fault" exception. I did open my database by sqliteBrowser and seen there an old object and new object. New object is correct. Old object(what should been removed) have relationships with objects, which been removed.

Also, UI may have access to property with managedObject when different thread updates an object.

How it can occurs? And how to prevent this? I read coreData troubleshooting with "CoreData could not fulfill a fault". I didn't found my problem since example.

I very confused about this. I have idea, but not sure, what it good way: What about if make the property not as managedObject, but as id(custom id, as NSNumber), owerload setter and getter. Setter receive same object, but have access to custom id and assign an id for property. Getter - fetches object by id, saved in property. Getter and setter will lock the NSLock at start and unlock this at end. Thread, which updates an object locks the lock too, until updating and saving is finished. Big thanks!

P.S. I very apologize, but I usually can't show my code by serious reason.


Solution

  • Nullifying a property of a class set to a managed object will not delete the managed object from the context or the store as both retain the managed object independent of any other retention. The object will continue to exist in memory and the store and will maintain any relationships you set for it until the context deletes the object.

    The "cannot fulfill a fault" error is occurring because the oldObject has relationships pointing to some other objects you have deleted. This is caused by an improper data model configuration that does not break the relationship when the target object is removed. Check your delete rules. One must be set to No Action.

    To actually remove the oldObject you must either tell the context to delete it explicitly with something like:

    [myManagedObjectContext deleteObject:oldObject];
    

    ... or set the relationship of the other entity to delete it using a cascade delete rule.