Realm (Swift):如何在迁移期间获取 MutableSet 数据?
Posted
技术标签:
【中文标题】Realm (Swift):如何在迁移期间获取 MutableSet 数据?【英文标题】:Realm (Swift): How to get at MutableSet data during migration? 【发布时间】:2021-11-30 17:47:13 【问题描述】:我有一个本地 Realm(使用 RealmSwift API 版本 10.15.1),它有一个我正在尝试迁移的 Player
对象。 Player
当前包含名为 preferredPositions
的字段,即 MutableSet<PositionClass>
。 Player
的定义如下:
@objc final class Player: Object
@Persisted(primaryKey: true) var playerId: ObjectId
@Persisted var name: String = ""
@Persisted var preferredPositions: MutableSet<PositionClass> = MutableSet<PositionClass>()
...
PositionClass
看起来像这样:
class PositionClass: Object
@Persisted(primaryKey: true) var positionClassId: String = ""
@Persisted var name: String = ""
@Persisted var order: Int = 0
@Persisted var abbreviation: String = ""
...
我想做一个迁移,将 preferredPositions
从 MutableSet<PositionClass>
更改为 List<PositionClass>
,因为现在我希望订购 preferredPositions
。
所以新的Player
看起来像:
@objc final class Player: Object
@Persisted(primaryKey: true) var playerId: ObjectId
@Persisted var name: String = ""
@Persisted var preferredPositions: List<PositionClass> = List<PositionClass>()
...
但是,我无法理解迁移配置中的魔法咒语来访问preferredPositions
数据。
在我的迁移中,我有:
let schemaVersion: UInt64 = 22
let config = Realm.Configuration(schemaVersion: schemaVersion,
migrationBlock: migration, oldSchemaVersion in
...
if (oldSchemaVersion < 22)
migration.enumerateObjects(ofType: Player.className()) oldObject, newObject in
if let preferredPositionsSet: MutableSet<PositionClass> = oldObject!["preferredPositions"] as? MutableSet<PositionClass>
let preferredPositionsList: List<PositionClass> = List()
preferredPositionsSet.forEach (positionClass: PositionClass) in
preferredPositionsList.append(positionClass)
newObject!["preferredPositions"] = preferredPositionsList
else
NSLog("preferredPositionsSet is nil.")
)
Realm.Configuration.defaultConfiguration = config
但是行
let preferredPositionsSet: MutableSet<PositionClass> = oldObject!["preferredPositions"] as? MutableSet<PositionClass>
总是返回零。我查看了调试器,似乎oldObject!["preferredPositions"]
是MutableSet<PositionClass>
。例如,如果我添加代码:
let preferredPositionsAny = oldObject!["preferredPositions"]
然后在它显示的调试器中查看preferredPositionsAny
:
所以,底层类型是正确的,但我不知道如何正确理解它。
或者我应该以不同的方式进行迁移?
【问题讨论】:
没有什么真的让我觉得“错了”。如果你这样做let preferredPositionsAny = oldObject!["preferredPositions"]
然后print(preferredPositionsAny)
和/或迭代集合会发生什么。您要打印到控制台的数据吗?我正在尝试验证数据是否实际可用而不是 nil。
谢谢@Jay,它显示它是一个Realm.Swift.MutableSet<RealmSwift.DynamicObject
,然后底层是一个MutableSet<PositionClass>
,所以是的,数据在那里。
【参考方案1】:
代码 TL;DR:
let schemaVersion: UInt64 = 22
let config = Realm.Configuration(schemaVersion: schemaVersion,
migrationBlock: migration, oldSchemaVersion in
...
if (oldSchemaVersion < 22)
migration.enumerateObjects(ofType: Player.className()) oldObject, newObject in
let newRealm = newObject!.realm
let preferredPositionsList: List<PositionClass> = List()
let preferredPositionsSet = oldObject!.dynamicMutableSet("preferredPositions")
preferredPositionsSet.forEach positionClass in
if let newPositionClass = newRealm?.object(ofType: PositionClass.self, forPrimaryKey: positionClass["positionClassId"])
preferredPositionsList.append(newPositionClass)
newObject!["preferredPositions"] = preferredPositionsList
更完整的答案:
有几件事我弄错了:
-
“旧”对象的数据类型不是
MutableSet<PositionClass>
,而是MutableSet<DynamicObject>
。这就是为什么MutableSet<PositionClass>
的演员总是返回nil
。
还有一种更清晰的方法来获取旧的MutableSet
,所以不要调用
let preferredPositionsSet = oldObject!["preferredPositions"] as! MutableSet<DynamicObject>
来自https://***.com/a/37588630/1204250我发现
let preferredPositionsSet = oldObject!.dynamicMutableSet("preferredPositions")
这似乎有返回相同的对象,但同样,更清楚一点
-
从这个答案:https://***.com/a/37588630/1204250,要使用现有的
PositionClass
实例重新填充新的List
(而不是创建新实例),您需要从领域获取数据。但是为了获取参数来获取数据。由于“旧”MutableSet
包含 DynamicObject
,因此您需要使用命名字段的 DynamicObject 方法来访问它,例如positionClass["positionClassId"]
而不是访问实际基础对象类型的属性,例如positionClass.positionClassId
。所以这就是
let newRealm = newObject!.realm
if let newPositionClass = newRealm?.object(ofType: PositionClass.self, forPrimaryKey: positionClass["positionClassId"])
...
来自。
【讨论】:
非常有趣的发现。当我尝试使用dynamicMutableSet
时,XCode 将该行标记为以下错误Value of type 'MigrationObject' (aka 'DynamicObject') has no member 'dynamicMutableSet'
。您使用的是什么版本的 Realm,因为我在文档中根本找不到该参数。
嗯.. 我在 10.15.1。我可能会很快更新到最新版本。
@Jay 我刚刚更新到 10.17.0,它仍然对我有用。以上是关于Realm (Swift):如何在迁移期间获取 MutableSet 数据?的主要内容,如果未能解决你的问题,请参考以下文章
在同一个项目中同时使用 Realm Swift 和 Realm Objective-C
Realm Swift 2.0:“不允许操作”- 仅在设备上