My Core Data experiences
My Core Data experiences
- Subject: My Core Data experiences
- From: Brian Williams <email@hidden>
- Date: Sun, 21 Jan 2007 18:31:13 -0800 (PST)
Hi Cocoa-Dev,
In my struggles with Core Data I have discovered some things for my self that
are not discussed in the documentation. I hope that my experience will save
someone grief in the future. I would also like to hear other peoples solutions
and please fell free to disabuse me of any spurious ideas.
1) Life cycle and undo / redo:
The documentation says "It is important to appreciate that Core Data "owns" the
life-cycle of managed objects." It goes on to say that awakeFromFetch and
awakeFromInsert should be used for any extra setup and then didTurnIntoFault
should be used in place of dealloc. About didAwakeFromFetch it specifically
says "awakeFromFetch is invoked when an object is re-initialized from a
persistent store". While this is all true what is not said is that if you undo
to a time before you managed object existed, didTurnIntoFault will be called,
but that on redo neither awakeFromFetch nor awakeFromInsert will be called. The
result is that you cannot depend on doing any setup that is not reflected in
the model. This leads rule one:
All managed object state must be in the model, even temporary values.
So that means that there is no way to reliably setup observers in
NSManagedObjects, or retain anything for that mater. Maybe it's obvious to
others, but I got burned on that one.
2) Accessor methods for remove<key>Object are called twice
In a to-many relation with a Parent and a Child you might have one Parent
having many children but a child only having one Parent (ignoring biology for a
moment). The Child would have a setParent method and the Parent would have a
addChildObject method and a removeChildObject method. These methods are called
when the relationships are changed. However this does not happen as you might
expect. If you for instance delete a child, the Parent's removeChildObject is
frequently called twice for the same child. Furthermore when the remove method
is called the first time, the child has already been removed from the parent
and vice versa.
So the accessor functions for removal of a Child C from a Parent P are called
like this;
C.setParent(nil)
C.willChangedValue
C.parent() returns P
C didChangeValue
C.parent() returns nil
P.removeChildObject(C)
P.removeChildObject(C)
The result is that you can't easily do anything upon removal of an object from
a relationship. This can be solved by having a "removed" attribute in the child
that you set on the first removal so that you don't do anything twice for the
same object. I don't have a good solution for many-to-many relations. Brings
me to my second and last rule;
Don't do anything with the accessors if you can help it.
If you do, you run the risk of an inconsistent state when redoing or calling
things twice.
One last thing:
I have been looking for a nice way of dealing with unsupported data types that
are used in many different Entities. For instance NSPoint, NSSIze, NSColor, I
have several Entities that have a location on screen and they all have the same
code for dealing with size and position. I tried making size and position
entities, but that was also a mess and required one-way links.
OK those are two land-mines that I have stepped on with Core Data, (plus a
gripe added for good measure). I wish someone would write a book or at-least a
chapter about it.
Thanks for reading.
Brian
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden