1

I have looked over the docs on Realm's site and can't find anything that describes how to handle removing a property in a migration. I took a group of properties that were similar enough to each other and moved them to a new object. Something like:

class MyObject: Object {
    @objc dynamic var siteName = ""
    @objc dynamic var lat = 0.0
    @objc dynamic var lon = 0.0
    @objc dynamic var roadNames = ""
    @objc dynamic var startTime = ""
    @objc dynamic var endTime = ""
    @objc dynamic var comments: String = ""
    @objc dynamic var complete: Bool = false
}

And then I changed it to:

class Site: Object {
    @objc dynamic var siteName = ""
    @objc dynamic var lat = 0.0
    @objc dynamic var lon = 0.0
    @objc dynamic var roadNames = ""
} 

class MyObject: Object {
    @objc dynamic var site: Site?
    @objc dynamic var startTime = ""
    @objc dynamic var endTime = ""
    @objc dynamic var comments: String = ""
    @objc dynamic var complete: Bool = false
}

And my migration is

let block: MigrationBlock = { (migration: Migration, oldSchemaVersion) in
    if oldSchemaVersion < 1 {
        migration.enumerateObjects(ofType: MyObject.className()) { oldObject, newObject in
            newObject!["siteName"] = oldObject!["siteName"]
            newObject!["lat"] = oldObject!["lat"]
            newObject!["lon"] = oldObject!["lon"]
            newObject!["roadNames"] = oldObject!["roadNames"]

            // Delete old properties.
        }
    }
}

How should my migration delete properties?

Cody Harness
  • 1,116
  • 3
  • 18
  • 37

1 Answers1

1

If read the Realm guide on migrations, you'll see that in the comments in one of the code blocks, it says:

        // Nothing to do!
        // Realm will automatically detect new properties and removed properties
        // And will update the schema on disk automatically

So you don't need to worry about deleting properties because they are deleted automatically.

What you do need to worry about though, is how you migrate the other values. You should create a Site for each MyObject and assign properties to that Site, which I don't see you doing here. See this question for how to create a new Site in the migration block.

Your migration block should look something like:

migration.enumerateObjects(ofType: MyObject.className()) { oldObject, newObject in
    let site = migration.create(Site.className())
    site["siteName"] = oldObject!["siteName"]
    site["lat"] = oldObject!["lat"]
    site["lon"] = oldObject!["lon"]
    site["roadNames"] = oldObject!["roadNames"]
    newObject!["site"] = site
}
Sweeper
  • 213,210
  • 22
  • 193
  • 313
  • I wrote my question right before bed and forgot to copy the error I get when I run this. I'll get the exact text in the morning, but it did say the the siteName property (not sure which object) wasn't allowed. – Cody Harness May 08 '19 at 05:58
  • 1
    @CodyHarness Because your migration block is written wrongly. You are trying to set `siteName` of `newObject`. But in the new model, there is no `siteName`. I'll edit my answer to show you how to correctly write a migration block. – Sweeper May 08 '19 at 06:00
  • Thanks, I can't believe I missed that! Just curious, what's the difference between using `site["siteName"]` and `site.siteName`? – Cody Harness May 09 '19 at 02:40
  • @CodyHarness you only use `site[“siteName”]` in a migration block. – Sweeper May 09 '19 at 05:08