🥹

【iOS】Realmのメモ

2024/02/29に公開

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を渡すのと大差ない気も
  • 書き込んだ内容を別のスレッドですぐに取得しようとすると、反映されていない事がある
    • 別スレッドで realm.refesh() して同期する必要がある

Concurrency, Task, Actor

最近はConcurrencyでも使えるようになっています。

  • try await Realm()
    • MainActorでアクセスする場合 (ハマることは少ないがwriteでUIが重くなる事がある?)
  • try await Realm(actor: BackgroundActor.shared)
    • BackgroundActorで書き込みできる (のでUIを軽くできる)
    • ただしActor境界を越えるのは、Thread境界と同等の大変さやトラブルがある

こちらの記事が詳しいです
https://zenn.dev/aldagram_tech/articles/b588f15c35047a

SwiftUI, Combine

  • SwiftUI用に、いろいろ便利なProperty Wrapperが追加されている様子

Discussion