Search code examples
iosswiftcore-datacore-data-migration

How to perform CoreData model migration *only* to add constraint(s)


I have a rather big CoreData database with plenty of duplicates and I need to add constraints to avoid duplicates in the future.

Consequently, I need to migrate the existing model to a model with constraints with potential (or rather definite) loss of some duplicates.

Preferably, I would like to have control the over duplicates removal process via a callback or something.

In the worst case scenario I would probably have 2 MOC's and copy data one by one from one to another, but what would be a good approach to such a migration?

Now I am getting Domain=NSCocoaErrorDomain Code=134110 "An error occurred during persistent store migration." UserInfo={sourceURL=<...>, reason=Cannot migrate store in-place: constraint violation during attempted migration,

P.S. I realise that my question is similar to the ones below, but they are not answered. I tried lightweight migration as well and it failed in a similar way. Core Data: constraints changes required migration Issues while lightweight Core Data Migration


Solution

  • Well, you kind of overlooked the actual headline when you titled this question. Adding constraints is indeed trivial. However, your other requirement, deleting existing duplicates is in fact the heavier lift. For this, you need to do a Heavyweight Migration :)

    I spent a few minutes looking for a good tutorial on Heavyweight Migration but so far have only found blog posts mentioning it in passing as something to be avoided because it is difficult. I have done heavyweight migrations and disagree that it is difficult. It is actually pretty straightforward.

    To get started, open your project in Xcode and create the new version of the data model by cloning the current data model and then adding your constraints. This step is the same as if you were doing a lightweight migration. Next, click in the menu: File > New, then scroll down to Core Data and select Mapping Model. This is, of course, the NSMappingModel referred to in that Apple document I linked to. When included into your app target it will add a .cdm file to your app product's Resources. There will be some code to write too – a subclass of NSMigrationPolicy. This will be the callback or something which you are looking for. Let us know if you need help with these.