Core Data vs. ARC
1) Create NSManagedObjectContext
2) Fetch
2) Pass results to a method
I’ve seen ARC kill the MOC before line 3.
With at-autoreleasepool, you could optimize given advanced knowledge. Now you need advanced knowledge to not die.
The problem here is that Core Data expects that you will keep the managed object context alive as long as you are using any of its objects, but the objects do not retain their context:
Managed objects know what managed object context they’re associated with, and managed object contexts know what managed objects they contain. By default, though, the references between a managed object and its context are weak. This means that in general you cannot rely on a context to ensure the longevity of a managed object instance, and you cannot rely on the existence of a managed object to ensure the longevity of a context.
ARC will try to release the context after the last line of code that references it, even if this is before the end of the scope. (This is different from other automated reference counting systems, such as Python’s.) It doesn’t know that later code in that scope may use managed objects that assume their context is still alive. This was also a problem with Objective-C garbage collection; Core Data used weak references even though the collector could have cleaned up cyclic strong ones.
Some potential solutions:
Make sure the context is owned by some higher level object so that it stays alive. This may not make sense for temporary contexts, though.
With garbage collection, a workaround was to send an innocuous message such as
[context class]
at the end of the scope so as to keep the object alive until that point. This still works under ARC.You can annotate the context’s variable with the objc_precise_lifetime attribute to tell ARC that you want it kept alive until the end of the scope. As of Mac OS X 10.8, there is also the Foundation-level NS_VALID_UNTIL_END_OF_SCOPE macro for doing this:
Marks local variables of type
id
or pointer-to-ObjC-object-type so that values stored into those local variable are not aggressively released by the compiler during optimization. Instead, the values are held until either the variable is assigned to again, or the end of the scope of the local variable (such as in a compound statement or a method definition).
All of this makes me sad because something this basic should not be so error-prone, and it should not be getting worse with time. As Drance notes, all of this just worked with manual reference counting. An autoreleased context would automatically stay alive as long as it was needed. You could fine-tune object lifetimes for increased performance; now you have to do so to avoid crashes.
Arguably, this is a design flaw in Core Data rather than ARC. Why don’t objects retain their context?
As far as I can tell, the situation is actually worse with Swift. It uses ARC but doesn’t seem to have the equivalent of NS_VALID_UNTIL_END_OF_SCOPE
.
2 Comments RSS · Twitter
[…] Tsai raises an interesting topic: CoreData vs ARC don’t really work all that well […]