【问题标题】:Perform migration by adding List() and another model class通过添加 List() 和另一个模型类来执行迁移
【发布时间】:2015-12-16 08:27:58
【问题描述】:

我有以下型号

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类,请问如何执行迁移块?因为迁移文档中的示例只是演示原始类型。

【问题讨论】:

    标签: swift realm realm-migration


    【解决方案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 的示例代码集合中有 some sample code 展示了如何在迁移中处理 List 对象

    如果您将region 属性添加到Area 的目标是您可以找出这个Area 是哪个Region 对象的子对象,那么您不需要将其实现为模型属性.相反,您可以使用 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"
        }
    }
    

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


    原答案

    您是否真的有任何想要添加到这些新属性的数据?由于它看起来不像您,因此您不需要在迁移块中实现任何代码。

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

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

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

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

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

    【讨论】:

    • 我确实做到了。这就是为什么我要问“如何调试我的迁移顺便说一句?就像我的架构已经是版本 1,我如何更改回版本 0 来测试我的架构版本 1 架构”
    • 而且您不需要在迁移中写入块? @_@
    • 因为我实际上有一个具有区域和区域的 Outlet 类,我现在要做的是将这两者链接在一起
    • 哦!好的。我会更新我的答案。可悲的是,迁移只是一种方式。您无法将 Realm 文件恢复到版本 0。如果您想快速测试迁移 Realm 文件,请使用原始 Realm 文件的副本。
    • 那么如何访问域来获取我的出口,例如更新区域/区域模型?
    【解决方案2】:

    这是一个可能的解决方案,假设旧模式版本为 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))")
    

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

    【讨论】:

    • 抱歉,您可能知道,我是迁移领域的新手。但是我在哪里可以实现区域对区域和区域对区域?
    • 我能不能像这样定义它们......让我们说在字符串的情况下,首先是“”(空值)?
    • 当然,您可以将区域中的区域设置为可选,并在迁移到它的过程中设置 nil 值。如果您还没有要添加的区域,您可以删除 Region 类的迁移代码。
    • 如果 oldSchemaVersion
    • 如何调试我的迁移顺便说一句?如果我的架构已经是版本 1,我该如何更改回版本 0 来测试我的架构版本 1 架构
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-10-09
    • 2019-11-05
    • 2017-06-07
    • 2017-11-21
    • 1970-01-01
    • 2012-01-25
    • 1970-01-01
    相关资源
    最近更新 更多