2017-09-17 78 views
0

我的應用程序中有幾個領域管理對象,需要跟蹤它最後修改的時間戳。避免領域遞歸更改通知

可能爲此實現存儲庫編程模式,或者我可以記住每次在這些對象上進行更改時(這是一種後備的想法,聽起來很可怕)。

我所做的是創建一個單例對象,該對象監視要保留「最後修改」時間戳的對象的集合。這是在應用程序啓動時啓動的,並留意所有修改的集合。

一般的「流」是:

  • 等待更改通知
  • 在變化,循環修改後的指標
  • 檢查試圖訪問該對象之前存在(以防萬一)
  • 指數
  • realm.write一個新的最後修改日期的對象

正如你可能已經猜到已經(一nd,因爲我懷疑),realm.write更新我上次修改的時間戳,然後創建一個新的更改通知,這反過來又使時間戳更新。所以它最終會在第一次改變後永遠循環。

尋找最佳解決方案。

這裏是我已經實現:

class RealmCollectionLastModifiedMonitor { 
    static let shared = RealmCollectionLastModifiedMonitor() 

    private var formObjectNotificationToken: NotificationToken? 

    private init() { 
     startMonitoring() 
    } 

    deinit { 
     stopMonitoring() 
    } 

    func startMonitoring() { 
     let realm = try! Realm() 
     let caseforms = realm.objects(CaseForm.self) 

     formObjectNotificationToken = caseforms.addNotificationBlock { [weak self] (changes: RealmCollectionChange) in 
      switch changes { 

      case .initial: 
       // Do nothing for now - as i've not worked out what this is :P     
       break 

      case .update(_, let deletions, let insertions, let modifications): 

       // Some debug output 
       print("Form collection change: Deletions = \(deletions.count), Insertions = \(insertions.count), Modifications = \(modifications.count)") 

       // Loop the modificated indexes, get a reference to the form, then update the last modified timestamp 
       for i in modifications { 
        if caseforms.indices.contains(i) { 
         do { 
          try realm.write { 
           caseforms[i].lastModified = Date() 
          } 
         } catch { 
          print("Failed to update modified date") 
         } 
        } 
       } 

       break 

      case .error(let error): 
       // Do nothing for now - If a write fails, we could rollback, but it's not uber-important 
       break 
      } 
     } 
    } 

    func stopMonitoring() { 
     formObjectNotificationToken = nil 
    } 
} 

回答

2

不幸的是我的建議是你當前方法的重構。 您的意圖不是監視集合的一般更改,而是更改特定對象上的特定屬性。

這是我的,我覺得通過監視每個單獨的對象,你會更好地服務,這將允許你反思已經改變了對象的屬性。

例如,

func monitor(_ caseForm: CaseForm) -> NotificationToken { 
    return caseForm.addNotificationBlock { change in 
     switch change { 
      case .change(let properties): 
       guard properties.count > 0 !properties.first(where: { $0.name == "lastModified" }) else { return } 
        // modify last modified date 
      case .deleted: 
       break 
      case .error(let error): 
       // handle error 
      } 
     } 
    } 
} 
+0

感謝詹姆斯。你認爲這可以與插入和刪除的收集通知配對嗎?因此,如果我有一個用於刪除和插入的集合監視器,然後爲各個對象創建(或刪除)對象通知?很明顯,我也需要在應用程序啓動時爲現有對象註冊通知。明天我會放棄它,但是我想我會提出這個問題,以防萬一你已經知道這是一個愚蠢的想法,我甚至不應該嘗試:P – TRG

+0

是的,但你必須確保你添加一個通知塊到集合通知回調之外的對象。一個簡單的方法就是在集合通知回調中執行'DispatchQueue.main.async {self.monitor(caseForm)}'。 –

+0

真棒,不會想到在塊外運行顯示器,謝謝James! – TRG