首页 文章

领域:防止对对象进行不必要的更新

提问于
浏览
2

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

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

问题是所有单元都重新加载,因为数据库中的所有对象都会更新,即使它们不是盲目地使用 realm.add(object, update:true) . Is there is a good way to prevent updating objects that haven't actually changed so that cell's aren't needlessly reloaded?

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

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

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

2 回答

  • 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)
    }
    
  • 0

    对于具有嵌套对象(列表)的对象,此修改后的解决方案似乎运行良好 .

    // 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
    }
    

相关问题