Wednesday, March 31, 2021

Replacing vs. Migrating Core Data Stores

Apple Frameworks Engineer:

Additionally you should almost never use NSPersistentStoreCoordinator’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 perform an APFS clone where possible.

Tom Harrington:

[This] method is almost totally undocumented, so you’re on your own working out how to use it. The dev forums post mentioned above is from summer 2020. The replacePersistentStore(...) method was introduced five years earlier in iOS 9, but the forum post was the first time most of the information appeared.

[This] is the first suggestion I’ve seen that migratePersistentStore(...) might not be a good idea anymore. It’s not deprecated and I haven’t seen any previous source recommending against its use.

There are some comments in the header.

Incidentally you won’t find this if you’re using Swift and ⌘-click on the function name. You need to find the Objective-C header. One way to do this in Xcode is to press ⌘-shift-O and start typing the class name.


Its declaration says it can throw. I tried intentionally causing some errors but it never threw. For example, what if sourceURL points to a nonexistent file? That seems like it would throw, especially since the function doesn’t return anything to indicate success or failure. It doesn’t throw, although there’s a console message reading Restore error: invalidSource("Source URL must exist").

He’s figured out a lot, though other important details like the APFS support remain a mystery.

Tom Harrington:

The demo app I’ve been using is now on GitHub. You can take a look here. Or go directly to the diff of replacing migrate with replace here.


The backup process is simpler than it used to be, because replace doesn’t have the same side-effect that migrate did of unloading the persistent store.


Even though the migrate and replace methods seem pretty similar, the semantics are slightly different when the destination is a currently-loaded store. My new restore code reflects that.


Comments RSS · Twitter

Leave a Comment