【问题标题】:Realm: prevent unnecessary updates to objects领域:防止对对象进行不必要的更新
【发布时间】:2016-08-06 21:16:07
【问题描述】:

我有一个设置,我从服务器获取一些 json 数据以填充表。数据有可能发生了变化,所以我每次都获取所有数据。我将该数据映射到 Realm 对象并将其保存到数据库中。主 ID 用于防止重复。

我使用 Realm 通知来保持 tableview/collection 视图与数据源同步。当服务器请求完成时,对象会更新或添加到数据库中,并且视图会自动重新加载。

问题是所有单元格都重新加载,因为数据库中的所有对象都已更新,即使它们实际上并没有什么不同,因为我只是盲目地使用realm.add(object, update:true)有没有一种好方法可以防止更新实际上没有更改的对象,以免不必要地重新加载单元格?

我尝试的解决方案是为 Realm 的 Object 类编写一个扩展,包括一个检查是否存在具有相同主 ID 的任何对象的函数,比较它们,如果它们不匹配,则添加/更新对象。但是,我有许多对象类,在不知道对象的类开始的情况下,我找不到从对象本身获取对象类型的方法。

// All subclasses of ServerObject have id as their primaryKey
let object = database.objectForPrimaryKey(type:???, key: self.id)

我不想将相同的 check-before-add 代码复制到我的每个类中,因为这很麻烦,所以我需要一些可以放入协议或扩展中的东西,或者只是一种完全不同的方式去处理服务器的响应。

【问题讨论】:

    标签: ios swift realm


    【解决方案1】:

    听起来你想要一些类似的东西:

    extension Object {
        public func hasChanges(realm: Realm) -> Bool {
            guard let obj = realm.objectForPrimaryKey(self.dynamicType, key: self["id"])
                else { return true }
    
            for property in obj.objectSchema.properties {
                let oldValue = obj[property.name]
                let newValue = self[property.name]
    
                if let newValue = newValue {
                    if oldValue == nil || !newValue.isEqual(oldValue) {
                        return true
                    }
                } else if oldValue != nil {
                    return true
                }
            }
            return false
        }
    }
    

    这将用作:

    let obj = MyObjectType()
    obj.id = ...;
    obj.field = ...;
    if obj.hasChanges(realm) {
        realm.add(obj, update: true)
    }
    

    【讨论】:

    • 这正是我要找的!当我回到办公桌前时,我会试一试。不过看起来很完美!
    • 一个更复杂的问题。如何处理列表属性?如果 newValue 和 oldValue 都是 List,那么即使列表相同,isEqual() 也会返回 false。
    【解决方案2】:

    对于具有嵌套对象(列表)的对象,这种修改后的解决方案似乎效果很好。

    // This function is general and can be used in any app
    private func hasChanges(realm: Realm) -> Bool {
        guard let obj = realm.objectForPrimaryKey(self.dynamicType, key: self["id"])
            else { return true }
    
        for property in obj.objectSchema.properties {
    
            // For lists and arrays, we need to ensure all the entries don't have changes
            if property.type == .Array {
                let list = self.dynamicList(property.name)
                for newEntry in list {
                    if newEntry.hasChanges(realm) {
                        return true
                    }
                }
    
            // For all properties that are values and not lists or arrays we can just compare values
            } else {
    
                let oldValue = obj[property.name]
                let newValue = self[property.name]
    
                if let newValue = newValue {
                    if oldValue == nil || !newValue.isEqual(oldValue) {
                        return true
                    }
                } else if oldValue != nil {
                    return true
                }
            }
        }
        return false
    }
    

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-17
    相关资源
    最近更新 更多