🥹
【iOS】Realmのメモ
Realmでハマりがちな挙動のメモ
Realmでハマりがちかつ忘れがちな箇所のメモ。
挙動や制約が分かりにくい上に、コンパイルエラーじゃなくて
実行時にExceptionで落ちるのが結構辛い。
Concurrencyで安全に使えるLocal DBはないのかな。
Realm
- あるRealmインスタンスから取得したRealmオブジェクトは、同じRealmインスタンスでwriteする必要がある
- "Object is already managed by another Realm. Use create instead to copy it into this Realm."
- Realm 5.x くらいまではそこまで厳しくなかった気が…
List
- appendの際は、オブジェクトがunmanagedで、同じprimaryKeyのオブジェクトが既にRealmに存在する場合、エラーになる
- Realmからmanagedなオブジェクトを取得して、プロパティを上書きした上でappendする必要がある
- これ自体は比較的シンプルなんだけど、ThreadやActorが絡むと面倒になる
Thread
- RealmインスタンスやObjectやResultは、作成・取得したのと同じスレッドでアクセスする必要がある
- freeze()することで、いちおう別スレッドでもアクセスできるようにはなる
- isFrozenがtrueになる
- が、更新してDBにwriteするためにはマネージドでなければならないので、結局その別スレッドで取得しなおして更新する必要がある
- ThreadSafeReferenceにして渡して、resolveしてから更新する手もあるが、idを渡すのと大差ない気も
- freeze()することで、いちおう別スレッドでもアクセスできるようにはなる
- 書き込んだ内容を別のスレッドですぐに取得しようとすると、反映されていない事がある
- 別スレッドで realm.refesh() して同期する必要がある
Concurrency, Task, Actor
最近はConcurrencyでも使えるようになっています。
-
try await Realm()
- MainActorでアクセスする場合 (ハマることは少ないがwriteでUIが重くなる事がある?)
-
try await Realm(actor: BackgroundActor.shared)
- BackgroundActorで書き込みできる (のでUIを軽くできる)
- ただしActor境界を越えるのは、Thread境界と同等の大変さやトラブルがある
こちらの記事が詳しいです
SwiftUI, Combine
- SwiftUI用に、いろいろ便利なProperty Wrapperが追加されている様子
Discussion