Realm Migration doesn't work
Asked Answered
R

10

22
    let config = Realm.Configuration(
        // Set the new schema version. This must be greater than the previously used
        // version (if you've never set a schema version before, the version is 0).
        schemaVersion: 1,

        // Set the block which will be called automatically when opening a Realm with
        // a schema version lower than the one set above
        migrationBlock: { migration, oldSchemaVersion in
            // We haven’t migrated anything yet, so oldSchemaVersion == 0
            if (oldSchemaVersion < 1) {
                // Nothing to do!
                // Realm will automatically detect new properties and removed properties
                // And will update the schema on disk automatically
            }
    })

    // Tell Realm to use this new configuration object for the default Realm
    Realm.Configuration.defaultConfiguration = config

    // Now that we've told Realm how to handle the schema change, opening the file
    // will automatically perform the migration
    let realm = try! Realm()

This was put in application(application:didFinishLaunchingWithOptions:)

In my test program, I have changed the fields in my object. I would like to remove everything in the database, and move to the new field types. I've copied the code above from the documentation, but it appears to do nothing. I still get these errors:

fatal error: 'try!' expression unexpectedly raised an error: Error Domain=io.realm Code=0 "Migration is required due to the following errors: 
- Property types for 'unit' property do not match. Old type 'string', new type 'int'
- Property 'reps' has been added to latest object model." UserInfo={NSLocalizedDescription=Migration is required due to the following errors: 
- Property types for 'unit' property do not match. Old type 'string', new type 'int'
- Property 'reps' has been added to latest object model.}: file   /Library/Caches/com.apple.xbs/Sources/swiftlang/swiftlang-700.1.101.15/src/swift/stdlib/public/core/

Any ideas?

Richert answered 4/1, 2016 at 19:20 Comment(1)
schemaVersion must be greater than the previously used version. It seems the current schema version might be greater than 1? Can you try to pass more larger number to schemaVersion parameter?Strikebreaker
L
7

As long as you're in local development only, I'd recommend to reset your Realm database instead of doing a migration. Migrations are the way to go, if you have already shipped a version of your app with another schema and want to keep user data.

You can delete the database by deleting the app from the simulator or the device. Alternatively you can use NSFileManager to delete the Realm file before accessing the database.

let defaultPath = Realm.Configuration.defaultConfiguration.path!
try NSFileManager.defaultManager().removeItemAtPath(defaultPath)
Laith answered 7/1, 2016 at 16:24 Comment(2)
This does not address the real issue, instead it just recommends to use migrations for production apps.Defile
Correct.. this error often happens when you update properties of you realm DB while DB already hold some data. After altering DB properties ie. renaming existing property or adding new property, realm and Swift doesn't know what to do with it hence the error. To fix it you need to clear you DB - easiest way is to uninstall you application and run build again. This solution worked for me.Clematis
S
14

I had a similar issue happening where my app would crash despite the fact that I added the default migration code in didFinishLaunchingWithOptions

The problem was that I was indeed initializing an instance of Realm in my first view controller as a class level property. So removing that class level realm object from my first ViewController fixed the issue.

import UIKit
import RealmSwift

class ViewController: UIViewController{
  let db = try! Realm() // Removing this solved my issue

  func doSomething(){
    let db = try! Realm() // Placed this here instead
  }
}

I instead created the object inside the function that needed it, which is a better approach anyway.

Swetiana answered 11/8, 2016 at 18:44 Comment(4)
Can confirm this was the issue I was having as well, thanks!Pandich
I can confirm this, tooLudmilla
This saved me! I was instantiating realm in my launch viewcontroller. I moved the instantiation to viewDidAppear, and now my migration is running! ThanksGrantgranta
This answer addresses the issue properly and works. Thanks.Defile
L
7

As long as you're in local development only, I'd recommend to reset your Realm database instead of doing a migration. Migrations are the way to go, if you have already shipped a version of your app with another schema and want to keep user data.

You can delete the database by deleting the app from the simulator or the device. Alternatively you can use NSFileManager to delete the Realm file before accessing the database.

let defaultPath = Realm.Configuration.defaultConfiguration.path!
try NSFileManager.defaultManager().removeItemAtPath(defaultPath)
Laith answered 7/1, 2016 at 16:24 Comment(2)
This does not address the real issue, instead it just recommends to use migrations for production apps.Defile
Correct.. this error often happens when you update properties of you realm DB while DB already hold some data. After altering DB properties ie. renaming existing property or adding new property, realm and Swift doesn't know what to do with it hence the error. To fix it you need to clear you DB - easiest way is to uninstall you application and run build again. This solution worked for me.Clematis
S
4

I also had this issue happening where my app would crash despite the fact that I added the default migration code in didFinishLaunchingWithOptions

As already stated here, the problem was that I was initializing an instance of Realm in my first view controller as a class level property.

BUT I couldn't just remove this instance and put it in the viewDidLoad, as I needed to use it in several functions.

The solution was actually to add the 'lazy' keyword, so the migration can be done before the initialization, as I found over here: https://www.selmanalpdundar.com/solution-of-realm-migration-error-code-10.html

import UIKit
import RealmSwift

class ViewController: UIViewController {
    lazy var realm = try! Realm() //added lazy and changed let to var
}
Supposed answered 21/8, 2020 at 19:45 Comment(0)
Q
3

Make sure you don't try to instantiate instance of Realm() before migration config is set in application(application:didFinishLaunchingWithOptions:). When it crashes check execution stack to find which instance raised exception. I had the same error, in my case Realm instance in one of my view controllers were instantiated before migration block was set.

Good luck

Quinine answered 1/6, 2016 at 22:58 Comment(0)
S
2

I often get the same fatal error too. This usually happens when you make changes to Realm Objects with a "Primary Keys". The quickest and most easy fix is to simply delete the app from the device or simulator - then run your project again.

Shrike answered 29/1, 2016 at 10:29 Comment(1)
How about when your app is on a remote user's device? What do you do then?Ludmilla
H
2

Are you sure that you updated your schemaVersion properly? If you set schemaVersion: 1 before you made changes, you need to change it to 2 in order for the migration to trigger.

Hemia answered 8/3, 2016 at 0:44 Comment(0)
Y
1

I find best solution:

You need add Realm migration code before didFinishLaunchingWithOptions in willFinishLaunchingWithOptions

func application(_ application: UIApplication, willFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {

    RealmManager.shared.configureRealm()

    return true
}
Yarrow answered 30/12, 2018 at 16:19 Comment(0)
C
1

Delete app from iPhone and install again. works good.

Capitalist answered 10/3, 2019 at 13:24 Comment(2)
When you have an app in production, you do not want to tell all your users to delete the app and install again. This is a bad practice and it should be avoid it.Microorganism
This only works if you have inserted a data using an object, and after that you changed the parameters of that object.Johanajohanan
I
0

In my case, changing the SchemaVersion worked

    static let SchemeaVersion: UInt64  = 28 // it was 27 previously

    var config = Realm.Configuration(
        // Set the new schema version. This must be greater than the previously used
        // version (if you've never set a schema version before, the version is 0).
        schemaVersion: RealmUtils.SchemeaVersion,
        
        // Set the block which will be called automatically when opening a Realm with
        // a schema version lower than the one set above
        migrationBlock: { migration, oldSchemaVersion in
          //  print(oldSchemaVersion)
            if (oldSchemaVersion < 27) { // THIS WAS 26
              //  print("Hello")
            }
    })
    // 🐞 Till the developement process
    // Delete database in version is lesser than 27 // THIS WAS 26 
    if config.schemaVersion < 27 { // THIS WAS 26
        config.deleteRealmIfMigrationNeeded = true
    }

Changing these 3 lines worked. However, I had to Re-Sync the stuff in my device.

Imprescriptible answered 22/9, 2021 at 12:33 Comment(0)
A
0

After a lot of debugging, we found that the issue was because of the way we had configured realm in our Notification Service Extension as advised here: https://github.com/realm/realm-swift/issues/4437.

When notification was received before first app launch, it was upgrading schema version from Notification Service Extension with empty migration block. Hence, it didn't ran the expected migration block post app launch. We managed to get it resolved by sharing our migration block across both these configuration.

Aromaticity answered 27/1, 2022 at 12:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.