{"id":10744,"date":"2015-02-28T11:37:19","date_gmt":"2015-02-28T16:37:19","guid":{"rendered":"http:\/\/mjtsai.com\/blog\/?p=10744"},"modified":"2015-02-28T11:40:30","modified_gmt":"2015-02-28T16:40:30","slug":"core-data-vs-arc","status":"publish","type":"post","link":"https:\/\/mjtsai.com\/blog\/2015\/02\/28\/core-data-vs-arc\/","title":{"rendered":"Core Data vs. ARC"},"content":{"rendered":"<p><a href=\"https:\/\/twitter.com\/drance\/status\/570649194588827648\">Matt Drance<\/a>:<\/p>\n<blockquote cite=\"https:\/\/twitter.com\/drance\/status\/570649194588827648\"><p>1) Create NSManagedObjectContext<\/p>\n<p>2) Fetch<\/p>\n<p>2) Pass results to a method<\/p>\n<p>I&rsquo;ve seen ARC kill the MOC before line 3.<\/p><\/blockquote>\n<blockquote cite=\"https:\/\/twitter.com\/drance\/status\/570664919382667264\"><p>With at-autoreleasepool, you could optimize given advanced knowledge. Now you need advanced knowledge to not die.<\/p><\/blockquote>\n<p>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 <a href=\"https:\/\/developer.apple.com\/library\/mac\/documentation\/Cocoa\/Conceptual\/CoreData\/Articles\/cdMemory.html\">do not retain<\/a> their context:<\/p>\n<blockquote cite=\"https:\/\/developer.apple.com\/library\/mac\/documentation\/Cocoa\/Conceptual\/CoreData\/Articles\/cdMemory.html\"><p>Managed objects know what managed object context they&rsquo;re associated with, and managed object contexts know what managed objects they contain. <em>By default<\/em>, 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.<\/p><\/blockquote>\n<p>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&rsquo;s.) It doesn&rsquo;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.<\/p>\n<p>Some potential solutions:<\/p>\n<ul>\n<li><p>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.<\/p><\/li>\n<li><p>With garbage collection, a workaround was to send an innocuous message such as <code>[context class]<\/code> at the end of the scope so as to keep the object alive until that point. This still works under ARC.<\/p><\/li>\n<li><p>You can annotate the context&rsquo;s variable with the <a href=\"http:\/\/clang.llvm.org\/docs\/AutomaticReferenceCounting.html#precise-lifetime-semantics\">objc_precise_lifetime<\/a> 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 <a href=\"https:\/\/developer.apple.com\/library\/mac\/documentation\/Cocoa\/Reference\/ObjCRuntimeRef\/index.html\">NS_VALID_UNTIL_END_OF_SCOPE<\/a> macro for doing this:<\/p>\n<blockquote cite=\"https:\/\/developer.apple.com\/library\/mac\/documentation\/Cocoa\/Reference\/ObjCRuntimeRef\/index.html\"><p>Marks local variables of type <code>id<\/code> 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).<\/p><\/blockquote><\/li>\n<\/ul>\n<p>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 <a href=\"https:\/\/twitter.com\/drance\/status\/570664919382667264\">Drance<\/a> notes, all of this just worked with manual reference counting. An autoreleased context would automatically stay alive as long as it was needed. You <em>could<\/em> fine-tune object lifetimes for increased <em>performance<\/em>; now you <em>have<\/em> to do so to avoid <em>crashes<\/em>.<\/p>\n<p>Arguably, this is a design flaw in Core Data rather than ARC. Why <em>don&rsquo;t<\/em> objects retain their context?<\/p>\n<p>As far as I can tell, the situation is actually worse with Swift. It <a href=\"https:\/\/developer.apple.com\/library\/mac\/documentation\/Swift\/Conceptual\/Swift_Programming_Language\/AutomaticReferenceCounting.html\">uses ARC<\/a> but doesn&rsquo;t seem to have the equivalent of <code>NS_VALID_UNTIL_END_OF_SCOPE<\/code>.<\/p>","protected":false},"excerpt":{"rendered":"<p>Matt Drance: 1) Create NSManagedObjectContext 2) Fetch 2) Pass results to a method I&rsquo;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 [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"apple_news_api_created_at":"","apple_news_api_id":"","apple_news_api_modified_at":"","apple_news_api_revision":"","apple_news_api_share_url":"","apple_news_coverimage":0,"apple_news_coverimage_caption":"","apple_news_is_hidden":false,"apple_news_is_paid":false,"apple_news_is_preview":false,"apple_news_is_sponsored":false,"apple_news_maturity_rating":"","apple_news_metadata":"\"\"","apple_news_pullquote":"","apple_news_pullquote_position":"","apple_news_slug":"","apple_news_sections":"\"\"","apple_news_suppress_video_url":false,"apple_news_use_image_component":false,"footnotes":""},"categories":[4],"tags":[55,69,109,288,31,46,30,571,54,71,232,901],"class_list":["post-10744","post","type-post","status-publish","format-standard","hentry","category-programming-category","tag-arc","tag-cocoa","tag-coredata","tag-garbargecollection","tag-ios","tag-languagedesign","tag-mac","tag-memory-management","tag-objective-c","tag-programming","tag-python","tag-swift-programming-language"],"apple_news_notices":[],"_links":{"self":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/10744","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/comments?post=10744"}],"version-history":[{"count":2,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/10744\/revisions"}],"predecessor-version":[{"id":10746,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/10744\/revisions\/10746"}],"wp:attachment":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/media?parent=10744"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/categories?post=10744"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/tags?post=10744"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}