2016-08-05 4 views
2

테이블을 채우기 위해 서버에서 일부 json 데이터를 가져 오는 설정이 있습니다. 데이터가 변경 될 가능성이 있으므로 매번 모든 데이터를 가져옵니다. 이 데이터를 Realm 오브젝트에 맵핑하고이를 데이터베이스에 보관합니다. 1 차 ID는 중복을 방지하기 위해 사용됩니다.영역 : 개체에 대한 불필요한 업데이트를 방지합니다.

렐름 알림을 사용하여 테이블 뷰/컬렉션보기를 데이터 소스와 동기화 된 상태로 유지합니다. 서버 요청이 완료되면 개체가 업데이트되거나 데이터베이스에 추가되고 뷰가 자동으로 다시로드됩니다.

문제는 데이터베이스의 모든 개체가 업데이트 되었기 때문에 모든 셀이 다시로드된다는 것입니다. 실제적으로 전혀 다르지는 않지만 단지 맹목적으로 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) 

그 문제를 묻는 있기 때문에 내 수업의 모든 일에 코드를 체크인하기 전에이-추가의 같은 덩어리를 복사하지 않는, 그래서 프로토콜 또는 확장에 갈 수있는 무언가가 필요하거나 서버의 응답을 처리하는 완전히 다른 방법입니다.

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

소리가 난다 잘.

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

내가 찾고있는 것이 맞습니다! 나는 내 책상으로 돌아 왔을 때 그걸 줄께. 그래도 완벽 해 보인다! – Erik

+0

하나 더 복잡합니다. 어떻게 목록 인 속성을 처리 할 수 ​​있습니까? newValue와 oldValue가 모두 List 이면 목록이 동일해도 isEqual()은 false를 반환합니다. – Erik

0

이 수정 된 솔루션은 작동하는 것 같다 당신의 라인을 따라 뭔가를 원하는 것처럼

관련 문제