0

I'm trying to work with one of the documented methods of migrating a realm database and setting the schema version. The kind of code I am using is:

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

This seems to be pretty standard code, and looks to be used by others. However, what seems to be tripping me up is where I am initialising the Realm instance which is causing the schema setting not to set or persist.

what I am struggling with is where to set the following code:

let uiRealm = try! Realm()
  • If I put this at the top of AppDelegate above @UIApplicationMain it initialises too early
  • If I create a controller file, that I intend to call a function within after the migration, and put the initialiser at the top of that it still doesn't work
  • If I put it within the class of a ViewController as in the code below I get the error Instance member uiRealm cannot be used on type XYZViewController

    import UIKit
    import RealmSwift
    
    class XYZViewController: UITableViewController,UIPickerViewDataSource,UIPickerViewDelegate {
    
        let uiRealm = try! Realm()
        var scenarios = uiRealm.objects(Scenario).filter("isActive = true ")
    
    }
    

So my question is: are there any best practices on where to initialise, and how best to migrate.

TiM
  • 15,812
  • 4
  • 51
  • 79
Michael Moulsdale
  • 1,488
  • 13
  • 34

1 Answers1

1

You need to make sure you've set your Configuration object as your Realm's default configuration before any other parts of your code call Realm().

Best practice is to not hold onto any references to Realm() unless you have a very good reason. Each time you call Realm(), it will return a previously cached instance of the object, so there are no performance benefits by creating a reference to an instance, and then hanging onto that one for the lifecycle of your app.

The best place for setting your Configuration object with the migration information is as soon as possible, before the code has had a chance to call Realm(). So the app delegate is a good place for this.

If you've got class properties that are relying on Realm() already being preconfigured, it might help to prepend the lazy keyword to those properties so their creation is delayed until you actually need them.

TiM
  • 15,812
  • 4
  • 51
  • 79
  • Thanks for this, so how do I convert the following into a lazy initialisation? scenarios = uiRealm.objects(Scenario).filter("isActive = true "). If I just put lazy in the front I get the error "Use of unresolved identifier uiRealm" – Michael Moulsdale Oct 22 '16 at 14:37
  • No worries! Hmm, is there any reason why you can't just use `Realm()` instead of uiRealm? – TiM Oct 23 '16 at 09:23
  • Hi, I got round this by declaring var scenarios: Results! at the top and then initialising the realm within each function. Again I was trying to do too much as a global eatable and have moved everything into functions. – Michael Moulsdale Oct 23 '16 at 09:32
  • Moreover. Adding the following code gets us the lazy version of the initialiser lazy var uiRealm:Realm = { return try! Realm() }() – Michael Moulsdale Oct 23 '16 at 10:20