在Realm swift中重命名类的最佳方法

问题描述 投票:4回答:1

我在iOS项目中使用了“通用”库。该库创建一个Realm数据库。到目前为止,我一直在iOS项目中使用这个库。我想现在使用与macOS项目相同的库。这是基于Foundation,并没有使用UIKit,为什么不呢?

这是问题:我有一个名为Collection的Realm类

Collection也是标准Swift协议的名称。

虽然我已经能够在我的iOS项目中逃脱这个名称冲突,但出于某种原因,我不能在我的MacOS项目上做同样的事情 - 它创建了一个名称集合。

我读到了可以这样使用的符号:

@objc(SpecialCollection)
class Collection: Realm.Object {
   let items: List<ItemObject>
   let name: String
   let url: String
  ....
}

因此,这解决了名称冲突问题。在ObjC中,名称会有所不同,但在Swift中,我不需要改变任何东西。

除了我的本地Realm数据库之外,这一切都很好。我有很多Collection对象应该重命名为SpecialCollection(因为Realm在Swift下使用ObjC)。我想执行迁移来执行此操作,但显然没有支持的方法来执行此操作吗?我注意到github上关于这个问题被“观看”的门票,但不幸的是,仍然没有已发布的解决方案来解决这个问题。

我所有的Collection对象都包含List对象(因此得名)。所以,我尝试在迁移中对所有Collection对象运行枚举...我只需要使用旧对象,并使用新名称创建一个新对象,如下所示:

 migration.enumerateObjects(ofType: "Collection", { (oldObject, _) in
    migration.create("SpecialCollection", value: oldObject)
 }

但由于oldObject有一个其他对象的列表,Realm的迁移将尝试创建任何List对象中的所有项目......这是无法完成的,因为它创建具有相同primaryKey值的对象(导致崩溃)。

所以,我不能保留旧名称(Collection),我无法转换为新名称,我不能只是删除用户的数据。所以,我真的陷入了僵局。

大段引用

我尝试在创建新对象之前修改oldObject,但是您无法在迁移中更改oldObject

唯一的规则是必须保留旧数据,我不能在这里破坏用户的领域。

感谢您的帮助。非常感谢。

ios swift macos realm realm-migration
1个回答
0
投票

我昨晚遇到了一个非常类似的问题。我有一些我想要重命名的Realm类,其中一个有一个List属性引用第二个类。因此,与您的问题相比,唯一的区别是我也重命名了ItemObject类。

所以这就是我做的方式:

  1. 首先迁移Collection类,创建SpecialCollection。
  2. 迁移时,遍历Collection的列表并为每个ItemObject创建新的SpecialItemObject并将其附加到新列表。
  3. 删除每个ItemObject。
  4. 现在枚举域中剩余的所有ItemObject并创建一个新的SpecialItemObject并将其值映射到。原因是您的领域中可能有其他ItemObject浮动,而不是绑定到列表。
  5. 删除所有剩余的ItemObject。

migration.enumerateObjects(ofType: "Collection")
{ (oldObject, newObject) in
    let specialCollection = migration.create(SpecialCollection.className())
    specialCollection["name"] = oldObject!["name"]
    specialCollection["url"] = oldObject!["url"]

    if let oldItems = oldObject!["items"] as? List<MigrationObject>,
       let newItems = specialCollection["items"] as? List<MigrationObject>
    {
        for oldItem in oldItems
        {
            let newItem = migration.create(SpecialItemObject.className())
            newItem["name"] = oldItem["name"]  // You didn't specify what was in your ItemObject so this example just assumes a name property.
            newItems.append(newItem)
            migration.delete(oldItem)
        }
    }
}
migration.deleteData(forType: "Collection")

// Now migrate any remaining ItemObject objects that were not part of a Collection.
migration.enumerateObjects(ofType: "ItemObject")
{ (oldObject, newObject) in
    let newItem = migration.create(SpecialItemObject.className())
    newItem["name"] = oldItem["name"]
}

// Now let's be sure we'll have no further ItemObject in our entire Realm.
migration.deleteData(forType: "ItemObject") 

所以这就是我昨晚在GitHub或SO或其他地方的可可领域中发现大部分内容之后我自己解决的问题。上面的示例仅与您提出的要求重命名ItemObject类的内容不同。您可以尝试创建新的ItemObject对象并以我在示例中显示的相同方式映射属性。我不明白为什么它不起作用。我已经提供了我的例子,我是如何解决自己的问题,因为我昨晚测试了一些迁移以证明它是可靠的。

由于你的问题差不多5个月了,我真的只是为后人发布这个答案。希望这有助于某人!

在iOS 11.3 sim / Xcode 9.3 / Swift 4.1上使用Realm 3.3.2进行测试

© www.soinside.com 2019 - 2024. All rights reserved.