2016-10-19 38 views
0

我的Realm數據庫中有一些對象。我需要從中刪除一個對象。 當我從我的Realm()實例中刪除我的對象時,對象已被刪除領域 - 數據庫在刪除後不是最新的

但是在執行刪除請求後,我需要從數據庫中檢索所有對象,但是這裏出乎意料,對象仍然在這裏

我想我有一個線程問題,或類似的東西。 我不知道在哪裏調查。

我的簡化代碼:

我的刪除方法:

func myDeleteFunc(completion :()->Void){ 
    let realm = try! Realm() 
    // ... 
    try! realm.write { 
     realm.delete(myObject) 
    } 
    completion() 
} 
// Here the object have been deleted from the realm instance, no problem 

此方法是從的viewController其中I執行完成塊調用。 此完成塊包含檢索我的境界數據庫中的所有對象請求:

執行的方法和完成塊的的viewController:

myDeleteFunc(completion: { 
    DispatchQueue.main.async { 
     let realm = try! Realm()     
     let objects = Array(realm.objects(MyObject.self).sorted(byProperty: "aProperty")) 
     // Here objects still contains the object that I have already deleted 
     // ... 
    } 
} 

我想我的2種realm情況不同,或線程之間有問題,因爲我有一個DispatchQueue.main.async

任何想法?

編輯:

我注意到,當我用的斷點檢查,有時它的工作原理。

因此,也許刪除請求尚未提交,並且我在刪除請求結束之前檢索對象?

回答

1

確保你把async塊自動釋放池:

myDeleteFunc(completion: { 
    DispatchQueue.main.async { 
     let realm = try! Realm()     
     let objects = Array(realm.objects(MyObject.self).sorted(byProperty: "aProperty")) 
     // Here objects still contains the object that I have already deleted 
     // ... 
    } 
} 

應該

myDeleteFunc(completion: { 
    DispatchQueue.main.async { 
     autoreleasepool { 
      let realm = try! Realm()     
      let objects = Array(realm.objects(MyObject.self).sorted(byProperty: "aProperty")) 
      // Here objects still contains the object that I have already deleted 
      // ... 
     } 
    } 
} 

確保您在其中創建了一個域實例的任何後臺線程做autoreleasepool { ... }包裝,主要在GCD中。


如果仍然不工作,你可以這樣做:

myDeleteFunc(completion: { 
    DispatchQueue.main.async { 
     autoreleasepool { 
      let realm = try! Realm()     
      realm.refresh() 
+0

它適用於autoreleasepool和realm.refresh(),謝謝,但爲什麼我要這樣做? – AnthonyR

+0

從技術上講'refresh()'部分更多的是解決方法,如果它仍然不起作用,儘管這意味着你仍然有開放的Realm實例,你應該用'autoreleasepool'塊來包裝以確保關閉它們。 – EpicPandaForce

+0

好吧,謝謝,我會檢查那些鬼! – AnthonyR

1

境界每個線程上分離交易以避免從一個線程更改立即影響到另一個。這種機制也避免了ORM固有的「缺陷」。

在您的代碼中,您可以選擇將領域刷新(提前)到最新狀態,在您控制的點上並且可以在刷新前後處理數據。

默認情況下,具有runloop(例如主線程)的線程上的領域會在runloop的每次迭代中自動推進。

在您的代碼示例中,您在從另一個線程提交後立即調用DispatchQueue.main.async,這意味着如果您已經在主線程上有Realm,則異步塊將處於相同狀態,並且不會包含最後一個承諾。

但是你可以在你的異步塊的開始,這將確保該塊看到,去年提交顯式調用Realm.refresh()

myDeleteFunc(completion: { 
    DispatchQueue.main.async { 
     let realm = try! Realm()     
     realm.refresh() 
     let objects = Array(realm.objects(MyObject.self).sorted(byProperty: "aProperty")) 
     // ... 
    } 
} 

見境界對Seeing Changes From Other Threads文檔的更多信息。

+0

謝謝,這更清楚。 最後一個問題:事實上,在我的刪除方法中,我在Realm實例的for循環中執行多個刪除查詢。 所以根據你所說的,如果兩個線程可以同時執行,我認爲即使我刷新了,我的代碼中的2個Realm實例也可能不同,不是嗎? 因爲是的,Realm會在上次提交時刷新。但刷新後,也許有些刪除查詢仍在等待提交no? – AnthonyR