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

时间:2016-08-05 02:46:31

标签: ios swift realm

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

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

问题在于所有单元格都会重新加载,因为数据库中的所有对象都会更新,即使它们实际上没有任何不同,因为我只是盲目地使用realm.add(object, update:true)是否有一种很好的方法可以阻止更新尚未实际更改过的对象,以便不必重新加载单元格?

我尝试的解决方案是为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 个答案:

答案 0 :(得分: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)
}

答案 1 :(得分: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
}