Issues While Lightweight Core Data Migration

Coredata Lightweight migration lost data

NSPersistentContainer enables Lightweight Migration by default. Delete the extra code.

And the migration doesn't delete any data. If the migration is not possible you get an error.

Core Data - Lightweight migration doesn't work

To set up an app for a lightweight migration, you need to insert the following lines into your CoreData framework where the Persistent Store is declared. These settings enable the options that support lightweight migrations (these are from a Swift 3.0 app so they may vary a bit if you're in 2.3):

NSMigratePersistentStoresAutomaticallyOption as NSObject: true                 
NSInferMappingModelAutomaticallyOption as NSObject: true

Once these lines are in place, CoreData will perform lightweight migrations correctly whenever they're required, including adding new entities, attributes, and relationships so you should be OK as long as you don't do anything that requires more action on your part - like changing the name of an entity or property.

CoreData lightweight migration crashes, even after adding a mapping model

The short version is that automatic lightweight migration can't make this change, even with a mapping model. You need to do a full manual migration to make this change. If you check out Apple's lightweight migration documentation, it says that

...if two existing entities do not share a common parent in the source, they cannot share a common parent in the destination.

This is what you're trying to do, but it can't happen automatically.

The longer answer to why gets into some details of how Core Data works. Xcode doesn't do a good job of making this obvious.

  • When you have two or more entities without a common parent entity, Core Data treats them as completely independent. Your SQLite has a Book table, an Author table, and so on.
  • When you have two or more entities with a common parent, Core Data treats them as special cases of the same table. Your SQLite has an IDManagedObject table. Core Data uses other logic to decide if an entry in that table is a Book or an Author or something else.

Because of this, what you're actually doing is merging more than one entity into a single new entity. Core Data doesn't know how to do that automatically, which is what it's telling you in that error message.

Core Data is only complaining about those two tables because they're the first ones it sees. It can't handle merging any of them, and it only mentions two tables because it's giving up before looking at the rest.

To make this change, you'll need to create a migration manager and write code to do the migration. Apple describes this in Customizing the Migration Process. Or, depending on what exactly you need, there might be other solutions that don't require adding a new parent entity.

Swift Core Data Migration Crash : syntax error in SELECT MAX(Z_PK) FROM (null)

Ok so I tried to dig inside the database and didn't find any strange-looking data.

I juste created a Mapping Model from the old to the new Partner Model, and specified that the new field should take the "default" value, and the migrations worked : so I guess I'll never know what was the real reason for this bug :)

My advice for anyone that would face this bug : try creating a Mapping Model (steps 7/8 in this tutorial)

Crashing after lightweight Core Data migration

I tried again from scratch and instead of renaming the variable, I created new one. This time app didn't crashed. I am sorry it is not real answer but it helped me to move on.

Lessons I learned:

  1. Do not confuse Core Data Model Identifier in Xcode inspector and renaming ID. There's one model identifier (I left it empty) and renaming ID for every property.
  2. If you have Core Data generated class with NSNumber, do not try to display them in console like this: label.text = "number = \(object.number)"

Do it like this:

label.text = "number = \(object.number.integerValue)"

This one gave me the same crash message, however it is not a problem if you're using NSDate.

I still have a problem when renaming variable. When I applied my commit again today I am getting the crash right on the start with the Can't find model for source store message. App in the simulator changed, so it looks like I can't reproduce this problem any more and instead have a new one.

Update

I had more practice and I think I was able to fix the crash described above.

I added next data model version - version 3 and introduced new variable. I did it like before, with switching current version from 2 to 3. Then app started to crash on launch with Can't find model for source store. I noticed that when I'm removing introduced variable the app is not crashing. I figure out that my Core Data couldn't migrate to version 3 because it already was on version 3:

  1. I changed version from 2 to 3. I didn't change Core Data model.
  2. I changed my code, fixed some bugs unrelated to Core Data.
  3. Built and ran the project in the simulator. Note, now the app in the simulator has data version 3.
  4. Changed Core Data model, built on simulator. It crashed after this step.

What I did to fix this:

  1. Delete introduced variable. You can live generated classes as it is.
  2. Change current version to previous. In my case, from 2 to 3.
  3. Run the app and quit it.
  4. Change Core Data current version and add new variable.
  5. Run the app — it works.

Update 2

I met with this problem again and my answer didn't helped. Still, event after everything I described above.

I found this answer which this time finally fixed the issue. The secret was that new attributes should not be optional and they should have default values.

Swift 4 in Xcode 9 - How to lightweight Core Data migration?

You can achieve like this:

let container = NSPersistentContainer(name: "YourDbModelName")
let description = NSPersistentStoreDescription()
description.shouldMigrateStoreAutomatically = true
description.shouldInferMappingModelAutomatically = true
container.persistentStoreDescriptions = [description]


Related Topics



Leave a reply



Submit