Realm使用update添加对象 - 忽略缺失值

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

我的主要问题是: 有没有一种方法可以为Realm模型指定默认值,该模型仅在从new创建Model时使用,但在realm从realm.add(thing, update: true)调用自动更新模型时被忽略

这是上下文的一些信息......

我有一个导入程序脚本,它从API中提取大量数据并将其导入域。忽略所有不相关的循环和嵌套结构,我基本上有这个:

let thing = SomeThing(value: [
    "id" : jsonData["id"].int!,
    "title" : jsonData["title"].string!,
    "system" : system
])

try! realm.write {
    realm.add(thing, update: true)
}

而我的SomeThing模型看起来像这样:

class SomeThing : Object {

    dynamic var id = 0
    dynamic var title = ""
    dynamic var system : System?

    dynamic var favourited = false

    override static func primaryKey() -> String? {
        return "id"
    }    
}

API不提供favourited布尔值,并在用户收藏对象时更新。但是因为模型默认值为false,所以当realm发现Thing已经存在时,它会更新值并将favourited重置为false

我知道明显的答案是将对象从领域拉出来并自己更新(如果它存在)所以我可以手动控制更新的内容(如果没有更好的选择,这就是我将要做的)但是可能有100个甚至是1000年的事情,所以我宁愿尝试避免首先将对象拉出来解决这个问题。

ios swift realm
3个回答
0
投票

Realm.create和Realm.add的行为差异已经解决为bug,选择了Realm.add行为。我在平均时间采用了以下方法,它将传入对象的所有属性与存储对象的默认值进行比较,并在适当时从存储中提取它们。还有一个要忽略的字段列表:

func hydrate<T: Object>(incoming: T, from realm: Realm, excluding excludedProperties: [String] = []) {
    #if DEBUG
    let propertyNames = incoming.objectSchema.properties.map { $0.name }
    excludedProperties.forEach { assert(propertyNames.contains($0), "Missing property \($0)")}
    #endif
    guard
        let key = T.primaryKey(),
        let identifier = incoming[key],
        let stored = realm.object(ofType: T.self, forPrimaryKey: identifier)
    else { return }
    let blankReference = T()
    incoming.objectSchema.properties
        .map { $0.name }
        .filter { !excludedProperties.contains($0) }
        .filter { incoming[$0] as AnyObject === blankReference[$0] as AnyObject }
        .forEach { incoming[$0] = stored[$0] }
}

4
投票

对于那些具有相同情况的人,我发现更新参数设置为realm.createtrue将满足您的需求。

使用我的问题中的方法,域将与现有对象和新对象相交并更新两者中存在的任何参数。因为在初始化对象时会创建favourited参数,所以领域会将此视为更改(我已经知道)。

但是,您可以改为使用realm.create并仅传递要更改的值。这实际上跳过了新对象的交叉(因为它不存在),并且只插入(或更新)传入的值。

所以这:

let thing = Something(value: [...whatever...])
try! realm.write { 
   realm.add(thing, update:true)
}

变为:

try! realm.write {
   let thing = realm.create(Something.self, value: [...whatever...], update: true)
}

注意:领域更新的技术实现确实远比某些对象差异或交叉更复杂。提供的解释仅用于帮助理解问题和解决方案,而不是记录其实际工作方式


0
投票

当你从你的服务器获得值时,做一个循环来获取具有匹配的SomeThing的已保存的id,然后更新它的titlesystem以及id,这样你就可以维护favourited,这是我认为的唯一方法,我不认为无论如何要做你提到的事情。

此外,您正在创建新对象并尝试使用已经内部的对象更新它将导致错误,我想,不知道现在可以吗?领域对象不仅包含您声明的属性,还包含其超类中的更多属性

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