执行从一个列表到另一个更新 属性 值的领域迁移
Perform Realm migration from one List to another updating property value
我正在尝试计算我的列表中有多少张卡片是相等的,并使用计数
更新新数量 属性
eg:
newObject!["list"] = [CardObject1, CardObject2, CardObject2,
CardObject2, CardObject3, CardObject3]
Assign to temporary list
var tempList = List()
CardObject1 (Update quantity property to 1)
CardObject2 (Update quantity property to 3)
CardObject3 (Update quantity property to 2)
tempList = [CardObject1, CardObject2, CardObject3]
Assign back to newObject!["list"] the updated/migrated list
newObject!["list"] = newList
崩溃在 newList.index(来自:卡)
* Terminating app due to uncaught exception 'RLMException', reason: 'Object type 'CardDTO' does not match RLMArray type 'DynamicObject'.'
* First throw call stack:
信息:
DeckDTO.swift
class DeckDTO: Object {
dynamic var id = NSUUID().uuidString
dynamic var name = ""
var list = List<CardDTO>()
override class func primaryKey() -> String {
return "id"
}
}
CardDTO.swift
class CardDTO: Object, Mappable {
// Other properties
dynamic var id = NSUUID().uuidString
dynamic var quantity: Int = 1
// Other properties
required convenience public init?(map: Map) {
self.init()
mapping(map: map)
}
func mapping(map: Map) {
//Map all my properties
}
override class func primaryKey() -> String {
return "id"
}
}
我正在尝试什么
if oldSchemaVersion < 2 {
migration.enumerateObjects(ofType: CardDTO.className()) { oldObject, newObject in
newObject!["quantity"] = 1
}
migration.enumerateObjects(ofType: DeckDTO.className()) { oldObject, newObject in
var newList = List<DynamicObject>()
let oldList = newObject!["list"] as! List<DynamicObject>
for card in oldList {
if let i = newList.index(of: card), i >= 0 {
newList[i] = (newList[i] as! CardDTO).quantity += 1 //some how do quantity++
print("increment quantity")
} else {
newList.append(card)
}
}
newObject!["list"] = newList
}
}
领域迁移块(及其动态 API)并不真正适合您的特定用例。 index(of:)
和 append()
都不能正确用于动态对象。
我对解决此问题的建议是在迁移块中简单地将 quantity
属性设置为 1,然后设置一个布尔标志,指示您需要执行牌组更新。然后,在您执行任何其他操作之前(可能在 application(_: didFinishLaunchingWithOptions:)
中),打开 Realm 并检查该标志。如果设置了该标志,则您可以打开 Realm 并使用普通 Realm API.
执行迁移
这是一些示例代码:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Get the configuration and set the migration block on it
var config = Realm.Configuration.defaultConfiguration
config.schemaVersion = 2
var needsMigrationToV2 = false
config.migrationBlock = { migration, oldSchemaVersion in
if oldSchemaVersion < 2 {
migration.enumerateObjects(ofType: CardDTO.className()) { oldObject, newObject in
newObject!["quantity"] = 1
}
needsMigrationToV2 = true
}
}
let realm = try! Realm(configuration: config)
// Run the rest of the migration using the typed API
if needsMigrationToV2 {
let allDecks = realm.objects(DeckDTO.self)
try! realm.write {
for deck in allDecks {
var uniqueCards : [CardDTO] = []
for card in deck.list {
if uniqueCards.contains(card) {
card.quantity += 1
} else {
uniqueCards.append(card)
}
}
deck.list.removeAll()
deck.list.append(objectsIn: uniqueCards)
}
}
}
return true
}
还有一件事要注意,List<T>
属性应该声明为 let
,而不是 var
,因为重新分配给 List<T>
属性 是一个错误。
我正在尝试计算我的列表中有多少张卡片是相等的,并使用计数
更新新数量 属性eg:
newObject!["list"] = [CardObject1, CardObject2, CardObject2, CardObject2, CardObject3, CardObject3]
Assign to temporary list
var tempList = List()
CardObject1 (Update quantity property to 1)
CardObject2 (Update quantity property to 3)
CardObject3 (Update quantity property to 2)tempList = [CardObject1, CardObject2, CardObject3]
Assign back to newObject!["list"] the updated/migrated list
newObject!["list"] = newList
崩溃在 newList.index(来自:卡)
* Terminating app due to uncaught exception 'RLMException', reason: 'Object type 'CardDTO' does not match RLMArray type 'DynamicObject'.' * First throw call stack:
信息:
DeckDTO.swift
class DeckDTO: Object {
dynamic var id = NSUUID().uuidString
dynamic var name = ""
var list = List<CardDTO>()
override class func primaryKey() -> String {
return "id"
}
}
CardDTO.swift
class CardDTO: Object, Mappable {
// Other properties
dynamic var id = NSUUID().uuidString
dynamic var quantity: Int = 1
// Other properties
required convenience public init?(map: Map) {
self.init()
mapping(map: map)
}
func mapping(map: Map) {
//Map all my properties
}
override class func primaryKey() -> String {
return "id"
}
}
我正在尝试什么
if oldSchemaVersion < 2 {
migration.enumerateObjects(ofType: CardDTO.className()) { oldObject, newObject in
newObject!["quantity"] = 1
}
migration.enumerateObjects(ofType: DeckDTO.className()) { oldObject, newObject in
var newList = List<DynamicObject>()
let oldList = newObject!["list"] as! List<DynamicObject>
for card in oldList {
if let i = newList.index(of: card), i >= 0 {
newList[i] = (newList[i] as! CardDTO).quantity += 1 //some how do quantity++
print("increment quantity")
} else {
newList.append(card)
}
}
newObject!["list"] = newList
}
}
领域迁移块(及其动态 API)并不真正适合您的特定用例。 index(of:)
和 append()
都不能正确用于动态对象。
我对解决此问题的建议是在迁移块中简单地将 quantity
属性设置为 1,然后设置一个布尔标志,指示您需要执行牌组更新。然后,在您执行任何其他操作之前(可能在 application(_: didFinishLaunchingWithOptions:)
中),打开 Realm 并检查该标志。如果设置了该标志,则您可以打开 Realm 并使用普通 Realm API.
这是一些示例代码:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Get the configuration and set the migration block on it
var config = Realm.Configuration.defaultConfiguration
config.schemaVersion = 2
var needsMigrationToV2 = false
config.migrationBlock = { migration, oldSchemaVersion in
if oldSchemaVersion < 2 {
migration.enumerateObjects(ofType: CardDTO.className()) { oldObject, newObject in
newObject!["quantity"] = 1
}
needsMigrationToV2 = true
}
}
let realm = try! Realm(configuration: config)
// Run the rest of the migration using the typed API
if needsMigrationToV2 {
let allDecks = realm.objects(DeckDTO.self)
try! realm.write {
for deck in allDecks {
var uniqueCards : [CardDTO] = []
for card in deck.list {
if uniqueCards.contains(card) {
card.quantity += 1
} else {
uniqueCards.append(card)
}
}
deck.list.removeAll()
deck.list.append(objectsIn: uniqueCards)
}
}
}
return true
}
还有一件事要注意,List<T>
属性应该声明为 let
,而不是 var
,因为重新分配给 List<T>
属性 是一个错误。