【问题标题】:How to perform migration of LinkingObject?如何执行 LinkingObject 的迁移?
【发布时间】:2019-12-10 17:00:29
【问题描述】:

我需要在不丢失父/所有者的情况下执行迁移。如何在迁移块中执行此操作?

迁移前

class Deck : Object {

    @objc dynamic var name : String = ""

    var cards = List<Card>()

}
class Card : Object {

    @objc dynamic var text = ""

    var parentCategory = LinkingObjects(fromType: Deck.self, property: "cards")

}

迁移后

class Deck : Object {

    @objc dynamic var name : String = ""

    let cards = LinkingObjects(fromType: Card.self, property: "owner")

}
class Card : Object {


    @objc dynamic var text = ""

    @objc dynamic var owner : Deck?


}



在新版本的应用程序中,当我制作新卡时,我会这样设置父级:

let decks = realm.objects(Deck.self)
owner = decks[index]

我只需要这样做,但在迁移的背景下:

 let realm = try! Realm()
        let decks : Results<Deck>? = realm.objects(Deck.self)
        do {
            try realm.write {
                if decks!.count > 0 {
                    for indexOfDeck in 0...decks!.count - 1 {
                        if decks![indexOfDeck].cards.count > 0 {
                            for indexOfCard in 0...decks![indexOfDeck].cards.count - 1 {
                                                       decks![indexOfDeck].cards[indexOfCard].owner = decks![indexOfDeck]

                                                   }
                        }

                    }
                }

            }

        }catch{

    } 

【问题讨论】:

  • 有几种方法可以做到这一点,但这是一个问题。一个牌组通常有一组独特的牌,牌组是父母/所有者,牌组属于该牌组。所以 List 代表多对关系,而 LinkingObjects 代表反向关系。这反映在您的第一个模型中。在您的第二个模型中,您将失去自动关系生成功能,因此如果将卡片添加到套牌中,则不会设置其所有者。这真的是你想要的吗?
  • 第二个问题:第一个模型中的 Card 类具有 LinkingObjects,这意味着一张卡可以链接回多个 Decks。是这样吗?
  • 您对我的第一个或第二个问题的回答是“是”吗?
  • 对于两者:)))))
  • 我只需要制作:let decks = realm.objects(Deck.self) owner = decks[index] 为了不失去父母。它会按我的预期工作。我已经检查过了。我用于此目的(用于 0..decks.count 中的索引)。

标签: ios swift migration realm realm-migration


【解决方案1】:

这个问题的挑战在于 LinkingObjects 不是持久化的 - 它们是经过计算的,因此无法直接迁移。

第二个挑战是原始卡片对象除了“文本”变量之外没有任何持久属性。

这是完成这项工作的代码。我们正在获取新的 Decks cards 属性,遍历它们并更新 Card 对象中的每个所有者属性以指向新的 Deck。

只要将卡片的 owner 属性设置到该牌组,该牌组 linkingCards 属性就会“拾取”该牌组,因为它是经过计算的。

let vers = UInt64(1)
let config = Realm.Configuration( schemaVersion: vers, migrationBlock: { migration, oldSchemaVersion in
     print(oldSchemaVersion)
     if (oldSchemaVersion < vers) {
        print("  performing migration")

         migration.enumerateObjects(ofType: Deck.className()) { oldDeck, newDeck in
            let cards = newDeck!["cards"] as! List<MigrationObject>
            for card in cards {
                card["owner"] = newDeck
            }
         }
     } else {
        print("no migration needed")
    }
 })

我的原始对象看起来像这样,应该与问题中的对象匹配

class Deck : Object {
    @objc dynamic var name : String = ""
    var cards = List<Card>() //current
}

class Card : Object {
    @objc dynamic var text = ""
    var parentCategory = LinkingObjects(fromType: Deck.self, property: "cards") //current
}

然后更新的对象看起来像这样

class Deck : Object {
    @objc dynamic var name : String = ""
    var cards = List<Card>() //current
    let linkingCards = LinkingObjects(fromType: Card.self, property: "owner") //new
}

class Card : Object {
    @objc dynamic var text = ""
    var parentCategory = LinkingObjects(fromType: Deck.self, property: "cards") //current
    @objc dynamic var owner : Deck? //new
}

【讨论】:

  • 谢谢 Jay,但我收到错误消息“无法将 'RLMResults' (0x1053c7e88) 类型的值转换为 'RealmSwift.List' (0x7fff89e4b968)”
  • @FilipCernov 嗯。我从一个功能齐全的项目中复制并粘贴了该代码。也许其中一个 var 名称已更改,或者您正在运行旧版本的 Realm?这是 macOS Catalina、XCode 11 和 Realm 4.1.1。我在答案中包含了我的模型,所以请检查一下。请注意,我更新的模型包括以前的模型变量,因此可以在迁移期间访问它们。不要忘记 LinkingObjects 是计算出来的,而不是持久化的。
猜你喜欢
  • 2013-02-15
  • 2012-05-09
  • 1970-01-01
  • 2015-01-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多