Daniel Daniel - 20 days ago 5
iOS Question

Realm migration issue

I apologize for loading what may seem like a duplicate question.

I am trying out Realm for the first time - I created a test project to work through it. I added another property to my model class and then got the error message about the change and migration being required. I followed the instructions and setup some code in AppDelegate for the migration (although the migration block was empty since I deleted all records) but the moment it hits my ViewController after starting again it crashes with "Provided schema version 0 is less than last set version 1" and I just can't get past it?

It fails in my ViewController on var realm = try! Realm()

What am I missing?

Answer

You seem to be doing it right. According to the realm documentation:

At the very minimum all we need to do is to update the version with an empty block to indicate that the schema has been upgraded (automatically) by Realm.

My guess is that you're either creating the configuration and migration, but not setting it as the default realm configuration, or setting the configuration too late (after instantiating a realm).

Based on the error you're getting

Provided schema version 0 is less than last set version 1

It seems that migration is not being executed at all. In any case, every time you update the schema you should also increment the schemaVersion in the realm configuration. That error means your configuration contains a version (0) lesser than the version of the existing database in disk (1). In that case your new configuration should have schemaVersion of at least 2 (anything higher than the version in disk).

Before ever instantiating the realm, as in your app delegate's application:didFinishLaunchingWithOptions:, you would minimally need something like the following according to your current schemaVersion.

let config = Realm.Configuration(
  schemaVersion: 2,  // Must be greater than previous version
  migrationBlock: { migration, oldSchemaVersion in
    if (oldSchemaVersion < 1) {
        // minimally this can be empty
    }
    if (oldSchemaVersion < 2) {
        // minimally this can be empty
    }
    print("Realm migration did run")  // Log to know migration was executed
  })

// Make sure to set the default configuration
Realm.Configuration.defaultConfiguration = config

I would also recommend you do some logging or set breakpoints both in the migration block, and in your view controller before instantiating realm. This way you can know whether a migration was ever executed.

However, since it seems that you are just learning realm, I recommend you ignore the details of migration for now. To avoid it you can uninstall your app from the device/simulator whenever you make changes to the database schema. Just make sure you use schemaVersion as 0 and you will always have a brand new database to work with, so migrations are not needed.

A second option is to use in-memory realms. These are not saved to disk so data is not persistent across app launches, but it still works like a normal realm database. This is perfect for early stage prototyping. To get one of these you just need to give your configuration an inMemoryIdentifier.

let config = Realm.Configuration(inMemoryIdentifier: "ThisRealmIsNotStored")
Realm.Configuration.defaultConfiguration = config