4

我有以下型号

class Area: Object {

// Specify properties to ignore (Realm won't persist these)

//  override static func ignoredProperties() -> [String] {
//    return []
//  }

    dynamic var id = 0
    dynamic var name = ""

    override static func primaryKey() -> String? {
        return "id"
    }

}

class Region: Object {

// Specify properties to ignore (Realm won't persist these)

//  override static func ignoredProperties() -> [String] {
//    return []
//  }

    dynamic var id = 0
    dynamic var name = ""

    override static func primaryKey() -> String? {
        return "id"
    }

}

我想添加let areas = List<Area>()到Region类和dynamic var region: Region?Area类,请问如何执行迁移块?因为迁移文档中的示例只是演示原始类型。

4

2 回答 2

1

收到澄清后编辑

好的。因此,由于您确实希望在将其添加到模型时进行预填充areas,因此您毕竟需要在迁移块中实现一些逻辑。

let migrationBlock: MigrationBlock = { migration, oldSchemaVersion in
    migration.enumerate(Region.className()) { oldObject, newObject in
        if oldSchemaVersion < 1 {
            let areas = newObject?["areas"] as? List<MigrationObject>
            // Add new objects to 'areas' as needed
        }
    }
}

在 Realm Swift 的示例代码集中,有一些示例代码展示了如何在迁移中处理 List 对象

如果您添加region属性的目标Area是找出Region这是哪个对象Area的子对象,那么您不需要将其实现为模型属性。相反,您可以使用linkingObjects(_: forProperty: )Realm 代表您解决这个问题。

class Area: Object {
    dynamic var id = 0
    dynamic var name = ""
    var regions: [Region] {
        return linkingObjects(Region.self, forProperty: "areas")
    }

    override static func primaryKey() -> String? {
        return "id"
    }
}

为了确认我在评论中所说的话,迁移是一种单向路径。它们不能降级到以前的架构版本。如果您想快速调试 Realm 文件的迁移过程,我建议将原始 Realm 文件放在一边并处理副本。


原始答案

您实际上是否有任何数据要添加到这些新属性中?因为它看起来不像你做的那样,所以你不需要在迁移块中实现任何代码。

只需增加 Realm 模式版本号,并提供一个空的迁移块。

let config = Realm.Configuration(
    schemaVersion: 1,
    migrationBlock: { migration, oldSchemaVersion in  

})

Realm.Configuration.defaultConfiguration = config

虽然迁移块不能为 nil,但您只需要在旧 Realm 文件中存在您想要在迁移期间操作的任何数据(即,将其移动到另一个属性)时将代码放入其中。如果您要添加全新的属性,则无需在迁移块内对它们执行任何操作。

进入 Realm 迁移的心态需要一点时间,但幸运的是,一旦你这样做了,你就会意识到它们比你想象的要容易。:)

(免责声明:我为 Realm 工作,但我在自己的一个发布的 iOS 应用程序中使用它,此时我已经对真实用户数据进行了多次迁移。:))

于 2015-12-16T13:16:36.590 回答
0

这是一个可能的解决方案,假设旧模式版本为 0,新模式版本为 1:

let migrationBlock: MigrationBlock = { migration, oldSchemaVersion in

  if oldSchemaVersion < 1 {
    //Migrate Regions
    migration.enumerate(Region.className()) { oldObject, newObject in
      if oldSchemaVersion < 1 {

        //Get appropriate area object for this Region Object
        let area = areaForRegion(newObject)  //<-- implement this
        newObject.areas.append(area)
      }
    }

    //Migrate areas
    migration.enumerate(Area.className()) { oldObject, newObject in
      if oldSchemaVersion < 1 {

        //Get appropriate region object for this area Object and set up the relation
        let region = regionForArea(newObject)  //<-- implement this
        newObject.region = region
      }
    }

  }
    print("Migration complete.")
}

Realm.Configuration.defaultConfiguration = Realm.Configuration(schemaVersion: 1, migrationBlock: migrationBlock)

// print out all migrated objects in the default realm
// migration is performed implicitly on Realm access
print("Migrated Area objects in the default Realm: \(try! Realm().objects(Area))")
print("Migrated Region objects in the default Realm: \(try! Realm().objects(Region))")

注意:您将需要实现为给定区域返回区域的方法,反之亦然。

于 2015-12-16T09:07:00.587 回答