How does deleteObject: work in coreData?
I just took the plunge and rewrote my App on top of CoreData (previously I was using my own internal save format).
Things are mostly working, although I'm a little confused by the behaviour of deleteObject:.
I have an object that is part of my graph, and when I delete it nothing seems to happen to the object. The object has relationships where some of them are "Cascade" and some are "Nullify". Every relationship to / from the object has an inverse relationship.
After I delete the object, the only thing that seems to change is that the "isDeleted" flag is set on my object. All of the relationships exist as they did before.
If I try to find the objects using a NSFetchRequest, it does not find the deleted objects. However, if I traverse my graph using the KVC relationships, the NSSet returned contains all of the objects including the deleted objects.
After I send the save: method to my ManagedObjectContext, then everything is as I expect.
When I do a deletion, do I need to manually nil out relationships I don't want or do I need to continuously save to keep my data sane? This seems very counter intuitive to me.
Is there anything that I can do to "commit" the deletion or at least make my object graph sane short of doing a save. It seems a little drastic to be doing a save every time I want to modify my graph.
p.s. Here is some of the behaviour that seems strange to me:
Before deleting the object, this is the "description" of the parent object which has a categoryObjs "to many" relationship:
categoryObjs = ( "0x613e1a0 <x-coredata://1A1AE9E7-66B1-4F4D-A7AB-07D4504CAE2C/TestCategory/p9>", "0x613e1b0 <x-coredata://1A1AE9E7-66B1-4F4D-A7AB-07D4504CAE2C/TestCategory/p12>", "0x613e190 <x-coredata://1A1AE9E7-66B1-4F4D-A7AB-07D4504CAE2C/TestCategory/p7>" );
After deleting the "p12" object (the middle one above), the state of the relationship does not change when accessed through KVC. If I try to fetch the TestCategory entities, then only two are found.
After a "save:" the p12 object disappears:
categoryObjs = ( "0x613e1a0 <x-coredata://1A1AE9E7-66B1-4F4D-A7AB-07D4504CAE2C/TestCategory/p9>", "0x613e190 <x-coredata://1A1AE9E7-66B1-4F4D-A7AB-07D4504CAE2C/TestCategory/p7>" );
Every time you call save:, your Managed Object Context must go back to the store and actually write the changes. This is expensive. Therefore, deleteObject: merely marks the object as deleted, which will actually be applied the next time you save. (Remember that this helps out with undo functionality too, it's just going against the way you want to do things.)
According to the documentation, the isDeleted property just states whether the object is going to be deleted upon the next commit, and sets an isDeleted flag on the object. Additionally, deleteObject: will remove the receiver from the context if it was never committed.
For example (where Objects A and B are NSManagedObject instances):
- Create Object A
- Save MOC
- Delete Object A
Object A has been marked for deletion but is not actually deleted until you perform step 2 again.
Contrast with this:
- Create Object B
- Delete Object B
Object B is gone, since it was never saved, there is no "marking for deletion". It's simply gone.
I'm just curious, are you using an NSFetchedResultsController for your tableview's datasource? It's worth looking in to, if you haven't already.
I think Core Data want to minimize memory & IO usage while deleteObject:, and do all the heaver jobs, like write sqllite file, in save:. That could be the most time-efficient way.