2016-10-19 8 views
0

レルムデータベースにオブジェクトがあります。私はそれからオブジェクトを削除する必要があります。 Realm()インスタンスからオブジェクトを削除すると、オブジェクトは完全に削除されますレルム - データベースは、削除後に最新ではありません

削除要求を実行した後、データベースからすべてのオブジェクトを取得する必要がありますが、ここで驚いたことに、オブジェクトはまだここにありますです。

スレッドの問題があると思います。 調査する場所がわかりません。

マイ簡略コード:

マイ削除方法:この方法は、私は完了ブロックを実行するのViewControllerから呼び出され

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 

。 、私は私の2つのrealmインスタンスが異なると思い

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

のViewController方法および完了ブロックを実行: この終了ブロックは私のレルムのデータベースからすべてのオブジェクトを取得要求が含まれています私はDispatchQueue.main.asyncを持っているのでスレッド間に問題があります。

アイデア?

EDIT:

私はブレークポイントをチェックしたときに、時にはそれが働くことに気づきました。

削除要求がまだコミットされておらず、削除要求の終了前にオブジェクトを取得している可能性がありますか?

答えて

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()'部分はまだ機能しない場合、回避策のほうがはるかに優れていますが、あなたが閉じるために 'autoreleasepool'ブロックでラップしておく必要があるRealmインスタンスがまだ開いていることを意味します。 – EpicPandaForce

+0

さて、ありがとう、私はそれらの幽霊をチェックします! – AnthonyR

1

レルムは、直ちに別に影響を与える一つのスレッドからの変更を避けるために、各スレッドでトランザクションを分離します。このメカニズムはまた、ORMに固有の「障害」を回避する。

コードでは、制御するポイントでレルムを最新の状態にリフレッシュ(前進)するか、リフレッシュの前後でデータを処理するかを選択できます。

runloop(メインスレッドなど)を持つスレッド上のレルムは、デフォルトでrunloopの各繰り返しで自動進行します。

コードサンプルでは、​​別のスレッドからコミットした直後にDispatchQueue.main.asyncを呼び出します。つまり、メインスレッドに既にレルムがある場合、非同期ブロックは同じ状態になり、最後のコミット。

しかし、あなたはこのブロックが最後にコミットすることを認識していることを確認しますあなたの非同期ブロックの開始時に明示的に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

ありがとう、これはより明確です。 最後の質問:私のdeleteメソッドでは、Realmインスタンスのfor-loopで複数の削除クエリを実行しています。 あなたが言ったことに基づいて、2つのスレッドを同時に実行できるのであれば、リフレッシュを行っても2つのRealmインスタンスが異なることがあります。 はいのため、レルムは最後のコミットでリフレッシュされます。しかし、リフレッシュ後、おそらくいくつかの削除クエリはまだコミットされていないために保留中ですか? – AnthonyR

関連する問題