{"id":21492,"date":"2018-05-10T16:52:11","date_gmt":"2018-05-10T20:52:11","guid":{"rendered":"https:\/\/mjtsai.com\/blog\/?p=21492"},"modified":"2018-05-15T15:20:13","modified_gmt":"2018-05-15T19:20:13","slug":"the-laws-of-core-data","status":"publish","type":"post","link":"https:\/\/mjtsai.com\/blog\/2018\/05\/10\/the-laws-of-core-data\/","title":{"rendered":"The Laws of Core Data"},"content":{"rendered":"<p><a href=\"https:\/\/davedelong.com\/blog\/2018\/05\/09\/the-laws-of-core-data\/\">Dave DeLong<\/a> (<a href=\"https:\/\/twitter.com\/davedelong\/status\/994311347247579136\">tweet<\/a>):<\/p>\n<blockquote cite=\"https:\/\/davedelong.com\/blog\/2018\/05\/09\/the-laws-of-core-data\/\"><p>In my conversations with developers, I&rsquo;ve heard a pretty common theme from them that &ldquo;Core Data is hard&rdquo; or &ldquo;Core Data is buggy&rdquo; or &ldquo;I could never get it to work right and gave up on it&rdquo;.<\/p>\n<p>I&rsquo;ve spent a lot of time using Core Data and thought I&rsquo;d share my &ldquo;Laws of Core Data&rdquo;. These are a set of rules I&rsquo;ve developed over time on how to use Core Data in such a way that it is almost <em>entirely<\/em> painless. When I follow these rules, I almost <em>never<\/em> have any problems using it.<\/p><\/blockquote>\n\n<p>Of particular note is that, <a href=\"https:\/\/mjtsai.com\/blog\/2015\/03\/30\/zarras-core-data-stack\/\">contra<\/a> <a href=\"https:\/\/mjtsai.com\/blog\/2015\/12\/20\/core-data-threading-demystified\/\">Zarra<\/a>, he thinks child contexts are usually unnecessary.<\/p>\n\n<p><a href=\"https:\/\/twitter.com\/colincornaby\/status\/994361904435875840\">Colin Cornaby<\/a>:<\/p>\n<blockquote cite=\"https:\/\/twitter.com\/colincornaby\/status\/994361904435875840\"><p>I find that when most people complain that CoreData is not thread safe out of the box, they&rsquo;re really saying &ldquo;I&rsquo;m able to ignore that my existing model code is also not thread safe.&rdquo;<\/p><\/blockquote>\n\n<p>Core Data has its issues&mdash;for example, there is a lot to learn, it is verbose, <a href=\"https:\/\/mjtsai.com\/blog\/2012\/06\/27\/sandboxing-core-data-and-migrations\/\">there<\/a> <a href=\"https:\/\/mjtsai.com\/blog\/2013\/03\/18\/core-data-auto-migration-and-sandboxing\/\">are<\/a> <a href=\"https:\/\/mjtsai.com\/blog\/2016\/02\/25\/core-data-join-table-records-not-deleted-in-ordered-relationship\/\">some<\/a> <a href=\"https:\/\/mjtsai.com\/blog\/2015\/06\/18\/core-data-bugs\/\">persistent<\/a> <a href=\"https:\/\/mjtsai.com\/blog\/2014\/11\/22\/core-data-relationships-data-loss-bug\/\">bugs<\/a>, and in some cases it&rsquo;s much slower than using SQLite directly&mdash;but overall I think it&rsquo;s <a href=\"https:\/\/twitter.com\/davedelong\/status\/994586676461686784\">unfairly maligned<\/a>.<\/p>\n\n<p>Update (2018-05-11): <a href=\"http:\/\/www.cimgf.com\/2018\/05\/10\/response-the-laws-of-core-data\/\">Marcus Zarra<\/a>:<\/p>\n<blockquote cite=\"http:\/\/www.cimgf.com\/2018\/05\/10\/response-the-laws-of-core-data\/\">\n<p>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.<\/p>\n<p>[&#8230;]<\/p>\n<p>An <code>NSManagedObject<\/code> <strong>is<\/strong> an <code>NSObject<\/code> that has additional functionality added. It should absolutely be treated as if it is an <code>NSObject<\/code> because it is an <code>NSObject<\/code>. <code>NSManagedObject<\/code> instances are your data objects and should be treated as such. Creating Plain Old Objects on top of <code>NSManagedObject<\/code> instances is asking for pain and data corruption.<\/p>\n<\/blockquote>\n<p>The crux of the issue is that <code>NSManagedObject<\/code> is an <code>NSObject<\/code> that doesn&rsquo;t obey that class&rsquo;s standard contract. So it should not be treated as such. That said, I&rsquo;m not sure there would be anything to gain by actually making it a separate root class. Creating plain objects on top of <code>NSManagedObject<\/code> 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.<\/p>\n<blockquote cite=\"http:\/\/www.cimgf.com\/2018\/05\/10\/response-the-laws-of-core-data\/\">\n<p>If your app talks to <em>anything<\/em> else then you will want to use parent-child contexts.<\/p>\n<p>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.<\/p>\n<p>A child context simplifies the transfer of notifications of data changes and greatly simplifies using Core Data in a multi-threaded environment.<\/p>\n<\/blockquote>\n\n<p>See also: <a href=\"https:\/\/twitter.com\/colincornaby\/status\/995012640270254080\">Colin Cornaby and Marcel Weiher<\/a>.<\/p>\n\n<p>Update (2018-05-15): See also: <a href=\"https:\/\/twitter.com\/steipete\/status\/996409638466785281\">Peter Steinberger<\/a>.<\/p>","protected":false},"excerpt":{"rendered":"<p>Dave DeLong (tweet): In my conversations with developers, I&rsquo;ve heard a pretty common theme from them that &ldquo;Core Data is hard&rdquo; or &ldquo;Core Data is buggy&rdquo; or &ldquo;I could never get it to work right and gave up on it&rdquo;. I&rsquo;ve spent a lot of time using Core Data and thought I&rsquo;d share my &ldquo;Laws [&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":"2018-05-15T19:20:16Z","apple_news_api_id":"ae9a3634-16dc-4814-a510-38207457e2aa","apple_news_api_modified_at":"2018-05-15T19:20:18Z","apple_news_api_revision":"AAAAAAAAAAAAAAAAAAAAAg==","apple_news_api_share_url":"https:\/\/apple.news\/Arpo2NBbcSBSlEDggdFfiqg","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":[800,109,31,1472,30,1529,71],"class_list":["post-21492","post","type-post","status-publish","format-standard","hentry","category-programming-category","tag-concurrency","tag-coredata","tag-ios","tag-ios-11","tag-mac","tag-macos-10-13","tag-programming"],"apple_news_notices":[],"_links":{"self":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/21492","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=21492"}],"version-history":[{"count":4,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/21492\/revisions"}],"predecessor-version":[{"id":21525,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/21492\/revisions\/21525"}],"wp:attachment":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/media?parent=21492"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/categories?post=21492"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/tags?post=21492"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}