gpt4 book ai didi

ios - Swift Realm 迁移创建从旧类型到新类型的引用

转载 作者:行者123 更新时间:2023-11-29 05:37:58 24 4
gpt4 key购买 nike

最初我有以下类(class):

@objcMembers public class NormalObjectRealm: Object {

// Shared
dynamic public var id: String?
dynamic public var title: String?
dynamic public var subTitle: String?
dynamic public var imageInfo: ImageInfoRealm?
dynamic public var descriptionString: String?
public var categories = List<String>()
public var count = RealmOptional<Int>()
public var episodes = List<String>()


public static let realmPrimaryKey: String = "id"

public override class func primaryKey() -> String? {
return NormalObjectRealm.realmPrimaryKey
}
}

@objcMembers public class ImageInfoRealm: Object {

dynamic public var id: String?
dynamic public var url: String?

public static let realmPrimaryKey: String = "id"

public override class func primaryKey() -> String? {
return ImageInfoRealm.realmPrimaryKey
}

}

但是现在 NormalObjectRealm 被合并到一个新类中,如下所示:

@objcMembers public class MediaObjectRealm: Object {

// Shared
dynamic public var id: String?
dynamic public var title: String?
dynamic public var subTitle: String?
dynamic public var imageInfo: ImageInfoRealm?
dynamic public var descriptionString: String?
public var categories = List<String>()
dynamic public var type: String?

// NormalObjectRealm
public var episodeCount = RealmOptional<Int>()
public var episodes = List<String>()

// OtherObjectRealm
dynamic public var urlOne: String?
dynamic public var urlTwo: String?
dynamic public var urlThree: String?
public var isExplicit = RealmOptional<Bool>()

public static let realmPrimaryKey: String = "id"

public override class func primaryKey() -> String? {
return MediaObjectRealm.realmPrimaryKey
}
}

我目前正在尝试在此处编写转换的迁移,其基本想法是将大部分字段从 NormalObjectRealm 转移到 MediaObjectRealm

这就是我的迁移 block 当前的样子

Realm.Configuration(schemaVersion: schemaVersion, migrationBlock: { migration, oldSchemaVersion in
if oldSchemaVersion < temp {
print("RealmMigration: Applying migration from \(oldSchemaVersion) to \(temp)")

migration.enumerateObjects(ofType: "NormalObjectRealm") { oldObject, newObject in
guard let oldObject = oldObject else {
return
}
guard let id = oldObject["id"] as? String else {
return
}
guard let title = oldObject["title"] as? String else {
return
}

guard let subTitle = oldObject["subTitle"] as? String else {
return
}

guard let imgInfo = oldObject["imageInfo"] else {
return
}
guard let count = oldObject["count"] as? RealmOptional<Int>? else {
return
}

guard let descriptionString = oldObject["descriptionString"] as? String? else {
return
}

let item = migration.create("MediaObjectRealm")
item["id"] = id
item["title"] = title
item["subTitle"] = subTitle
item["descriptionString"] = descriptionString
item["type"] = "myType"
item["episodeCount"] = episodeCount // Doesn't work either...

migration.enumerateObjects(ofType: "ImageInfoRealm") { oldImg, newImg in
guard let oldImg = oldImg else {
return
}

let inf = oldObject.value(forKey: "imageInfo")
print(inf)
let t = migration.create("ImageInfoRealm", value: inf)
print("doing it")
// print(t)
item.setValue(t, forKey: "imageInfo")

}
}
}
})

idtitlesubTitle 等(字符串?日期? 变量)被设置好并出现在新创建的 MediaObjectRealm DB-Entries 中。但是 ImageInfoRealm 类型的 imageInfo 不会...直接设置它,如下所示: item.setValue(oldObject.value(forKey: "imageInfo"), forKey: "imageInfo") (或 item["imageInfo"] = oldObject.value(forKey: "imageInfo")) 导致 Realm 崩溃并告诉我该对象来自另一个 Realm ,并且我得把它复制过来。

'Object is already managed by another Realm. Use create instead to copy it into this Realm.'

像上面的代码一样创建它会导致根本没有任何 MediaObjectRealm 类型的项目,即丢失所有数据(因为 NormalObjectRealm 也不再存在) 。我错过了什么吗?我基本上想要的是从 NormalObjectRealm 获取链接/引用并将其复制到新的 MediaObjectRealm

最佳答案

经过长时间的测试并尝试不同的可能性,我成功地迁移了数据。这是我为实现这一目标所做的事情。

我用它作为基础:

class RealmMigrationObject {
let migration: () -> ()

init(migration: @escaping () -> ()) {
self.migration = migration
}
}

以及从中派生的类。像这样的东西:

class MigrationObjectToThree: RealmMigrationObject {

init() {
super.init(migration: MigrationObjectToThree.migration)
}

private static func migration() {
print("Migration to three | migration")

var imageInfos: [ImageInfo] = []

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

print("Migration to three | migrationBlock")
print("RealmMigration: Applying migration from \(oldSchemaVersion) to 3")

migration.deleteData(forType: "ExploreSectionObjectRealm")

migration.enumerateObjects(ofType: "ImageInfoRealm") { oldInfo, newObject in
guard let oldInfo = oldInfo else {
return
}

guard let id = oldInfo["id"] as? String,
let url = oldInfo["url"] as? String,
let url500 = oldInfo["url500"] as? String,
let url400 = oldInfo["url400"] as? String,
let url300 = oldInfo["url300"] as? String,
let url200 = oldInfo["url200"] as? String,
let url100 = oldInfo["url100"] as? String,
let colorString = oldInfo["color"] as? String,
let color = UIColor(hexString: colorString) else {
return
}
imageInfos.append(ImageInfo(id: id,
url: url,
url500: url500,
url400: url400,
url300: url300,
url200: url200,
url100: url100,
color: color))
}

})


Realm.Configuration.defaultConfiguration = config
do {
let realm = try Realm(configuration: config)
print("Realm is located at: \(realm.configuration.fileURL?.description ?? "")")
print(realm.configuration.fileURL?.description ?? "") // Printing here on purpose as it's easier to copy
} catch {
print("Realm Error: \(error), trying to rebuild realm from scratch")

let deleteMigrationConfig = Realm.Configuration(schemaVersion: RealmHelper.schemaVersion,
deleteRealmIfMigrationNeeded: true)
do {
_ = try Realm(configuration: deleteMigrationConfig)
} catch {
print("Failed to instantiate: \(error.localizedDescription)")
}
}

RealmHelper.removeRealmFiles()
Realm.Configuration.defaultConfiguration = Realm.Configuration(schemaVersion: 3)

imageInfos.forEach({ $0.save() })
}
}

从此,我刚刚为当前架构版本和目标架构版本之间的差异创建了所有迁移,并在所有迁移上循环,只需执行该给定对象的 migration 函数。

关于ios - Swift Realm 迁移创建从旧类型到新类型的引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56852124/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com