{"id":32029,"date":"2021-03-31T10:08:13","date_gmt":"2021-03-31T14:08:13","guid":{"rendered":"https:\/\/mjtsai.com\/blog\/?p=32029"},"modified":"2021-03-31T10:17:58","modified_gmt":"2021-03-31T14:17:58","slug":"replacing-vs-migrating-core-data-stores","status":"publish","type":"post","link":"https:\/\/mjtsai.com\/blog\/2021\/03\/31\/replacing-vs-migrating-core-data-stores\/","title":{"rendered":"Replacing vs. Migrating Core Data Stores"},"content":{"rendered":"<p><a href=\"https:\/\/developer.apple.com\/forums\/thread\/651325\">Apple Frameworks Engineer<\/a>:<\/p>\n<blockquote cite=\"https:\/\/developer.apple.com\/forums\/thread\/651325\"><p>Additionally you should almost never use <code>NSPersistentStoreCoordinator<\/code>&rsquo;s <code>migratePersistentStore<\/code> method but instead use the newer <code>replacePersistentStoreAtURL<\/code>. (you can replace emptiness to make a copy). The former loads the store into memory so you can do fairly radical things like write it out as a different store type. It pre-dates iOS. The latter will perform an APFS clone where possible.<\/p><\/blockquote>\n\n<p><a href=\"https:\/\/atomicbird.com\/blog\/mostly-undocumented\/\">Tom Harrington<\/a>:<\/p>\n<blockquote cite=\"https:\/\/atomicbird.com\/blog\/mostly-undocumented\/\">\n<p>[This] method is almost totally undocumented, so you&rsquo;re on your own working out how to use it. The dev forums post mentioned above is from summer 2020. The <code>replacePersistentStore(...)<\/code> method was introduced five years earlier in iOS 9, but the forum post was the first time most of the information appeared.<\/p>\n<p>[This] is the first suggestion I&rsquo;ve seen that <code>migratePersistentStore(...)<\/code> might not be a good idea anymore. It&rsquo;s not deprecated and I haven&rsquo;t seen any previous source recommending against its use.<\/p>\n<\/blockquote>\n<p>There are some comments in the header.<\/p>\n<blockquote cite=\"https:\/\/atomicbird.com\/blog\/mostly-undocumented\/\"><p>Incidentally you won&rsquo;t find this if you&rsquo;re using Swift and &#x2318;-click on the function name. You need to find the Objective-C header. One way to do this in Xcode is to press &#x2318;-shift-O and start typing the class name.<\/p>\n<p>[&#8230;]<\/p>\n<p>Its declaration says it can throw. I tried intentionally causing some errors but it never threw. For example, what if <code>sourceURL<\/code> points to a nonexistent file? That seems like it would throw, especially since the function doesn&rsquo;t return anything to indicate success or failure. It doesn&rsquo;t throw, although there&rsquo;s a console message reading <code>Restore error: invalidSource(\"Source URL must exist\")<\/code>.<\/p>\n<\/blockquote>\n\n<p>He&rsquo;s figured out a lot, though other important details like the APFS support remain a mystery.<\/p>\n\n<p><a href=\"https:\/\/atomicbird.com\/blog\/core-data-backups-redux\/\">Tom Harrington<\/a>:<\/p>\n<blockquote cite=\"https:\/\/atomicbird.com\/blog\/core-data-backups-redux\/\"><p>The demo app I&rsquo;ve been using is now on GitHub. You can take a look <a href=\"https:\/\/github.com\/atomicbird\/CDMoveDemo\">here<\/a>. Or go directly to the diff of replacing <code>migrate<\/code> with <code>replace<\/code> <a href=\"https:\/\/github.com\/atomicbird\/CDMoveDemo\/commit\/fd60b4ca11502dc66329af9f9337826514b52156#diff-6b98e02baf6f7418533b1d2df2671bd7df4b784ae2c9c0388e9d6a411aa65c97\">here<\/a>.<\/p>\n<p>[&#8230;]<\/p>\n<p>The backup process is simpler than it used to be, because <code>replace<\/code> doesn&rsquo;t have the same side-effect that <code>migrate<\/code> did of unloading the persistent store.<\/p>\n<p>[&#8230;]<\/p>\n<p>Even though the <code>migrate<\/code> and <code>replace<\/code> methods seem pretty similar, the semantics are slightly different when the destination is a currently-loaded store. My new restore code reflects that.<\/p><\/blockquote>\n\n<p>Previously:<\/p>\n<ul>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2021\/03\/02\/apple-developer-forums-can-now-monitor-threads\/\">Apple Developer Forums Can Now Monitor Threads<\/a><\/li>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2020\/05\/29\/backing-up-core-data-stores\/\">Backing Up Core Data Stores<\/a><\/li>\n<\/ul>","protected":false},"excerpt":{"rendered":"<p>Apple Frameworks Engineer: Additionally you should almost never use NSPersistentStoreCoordinator&rsquo;s migratePersistentStore method but instead use the newer replacePersistentStoreAtURL. (you can replace emptiness to make a copy). The former loads the store into memory so you can do fairly radical things like write it out as a different store type. It pre-dates iOS. The latter will [&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":"2021-03-31T14:08:17Z","apple_news_api_id":"41c5830f-bfad-4f2d-b81d-b9733c5a8e83","apple_news_api_modified_at":"2021-03-31T14:18:02Z","apple_news_api_revision":"AAAAAAAAAAAAAAAAAAAAAA==","apple_news_api_share_url":"https:\/\/apple.news\/AQcWDD7-tTy24HblzPFqOgw","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":[1395,109,164,31,1837,30,1891,71,901,226],"class_list":["post-32029","post","type-post","status-publish","format-standard","hentry","category-programming-category","tag-apple-file-system-apfs","tag-coredata","tag-documentation","tag-ios","tag-ios-14","tag-mac","tag-macos-11-0","tag-programming","tag-swift-programming-language","tag-xcode"],"apple_news_notices":[],"_links":{"self":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/32029","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=32029"}],"version-history":[{"count":2,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/32029\/revisions"}],"predecessor-version":[{"id":32041,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/32029\/revisions\/32041"}],"wp:attachment":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/media?parent=32029"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/categories?post=32029"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/tags?post=32029"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}