The Laws of Core Data
Dave DeLong (tweet):
In my conversations with developers, I’ve heard a pretty common theme from them that “Core Data is hard” or “Core Data is buggy” or “I could never get it to work right and gave up on it”.
I’ve spent a lot of time using Core Data and thought I’d share my “Laws of Core Data”. These are a set of rules I’ve developed over time on how to use Core Data in such a way that it is almost entirely painless. When I follow these rules, I almost never have any problems using it.
Of particular note is that, contra Zarra, he thinks child contexts are usually unnecessary.
I find that when most people complain that CoreData is not thread safe out of the box, they’re really saying “I’m able to ignore that my existing model code is also not thread safe.”
Core Data has its issues—for example, there is a lot to learn, it is verbose, there are some persistent bugs, and in some cases it’s much slower than using SQLite directly—but overall I think it’s unfairly maligned.
Update (2018-05-11): Marcus Zarra:
All of the internal workings of your Core Data stack, your persistence and data model absolutely should be stored in the persistent container and that container should be injected through your controllers in your application.
[…]
An
NSManagedObject
is anNSObject
that has additional functionality added. It should absolutely be treated as if it is anNSObject
because it is anNSObject
.NSManagedObject
instances are your data objects and should be treated as such. Creating Plain Old Objects on top ofNSManagedObject
instances is asking for pain and data corruption.
The crux of the issue is that NSManagedObject
is an NSObject
that doesn’t obey that class’s standard contract. So it should not be treated as such. That said, I’m not sure there would be anything to gain by actually making it a separate root class. Creating plain objects on top of NSManagedObject
instances can be a useful pattern. It has really simplified some of my code and made it faster and more robust. But I would only do this on a case-by-case basis, not as a regular part of using Core Data.
If your app talks to anything else then you will want to use parent-child contexts.
The parent context should be on the user interface thread (the main thread) and when you need to do asynchronous work with your data objects (importing or exporting) then you want to do that on another thread and that work should be done in a child context.
A child context simplifies the transfer of notifications of data changes and greatly simplifies using Core Data in a multi-threaded environment.
See also: Colin Cornaby and Marcel Weiher.
Update (2018-05-15): See also: Peter Steinberger.
2 Comments RSS · Twitter
"Keep your main queue context read-only" is what I agree, in an old iPhone, even write an object to disk causing the UI a little no responds for a little second.