iOSエンジニアのつぶやき

毎朝8:30に iOS 関連の技術について1つぶやいています。まれに釣りについてつぶやく可能性があります。

【Swift】Realm + RxSwift でデータの更新を通知する

今回は RxSwift で Realm のデータ(Object) の更新を通知する方法を簡単に紹介します👷‍♀️

それではやっていく

データの変更を通知するための Observable を返すメソッドは下記のようになります。Realm Object のインスタンスメソッド observe でデータの変更を受信できるようになります。またここで取得したデータは、Observable が破棄されたタイミングで監視をやめる必要があるので、Disposables.create のブロック内で token.invalidate() を呼び出します。

    func observeProfile() -> Observable<RealmAccount> {
        let account = getAccount() // RealmからRealmAccount データを取得する
        return Observable<RealmAccount>.create {observer -> Disposable in
            let token = account.observe { result in
                if case .change(let object, _) = result, let newAccount = object as? RealmAccount {
                    observer.onNext(newAccount)
                    observer.onCompleted()
                }
            }
            return Disposables.create {
                token.invalidate()
            }
        }
    }

今回は observe の引数 result.change だった場合にイベントを通知するようにしていますが、この他にも deleteerror などのタイプがあります。また、コメントの通り error が呼ばれた後は再度コールバックが呼ばれないので、注意が必要です。現在は、バックグランドで Realm を開いた場合にもに error になるそうです。

public enum ObjectChange<T> where T : RealmSwift.Object {

    /**
     If an error occurs, notification blocks are called one time with a `.error`
     result and an `NSError` containing details about the error. Currently the
     only errors which can occur are when opening the Realm on a background
     worker thread to calculate the change set. The callback will never be
     called again after `.error` is delivered.
     */
    case error(_: NSError)

    /**
     One or more of the properties of the object have been changed.
     */
    case change(T, [RealmSwift.PropertyChange])

    /// The object has been deleted from the Realm.
    case deleted
}

change タイプでは、Associated ValueObject と、変更されたプロパティが配列で渡されます。詳しくは Realm ドキュメントを参照してください。

realm.io

参考

その他の記事

yamato8010.hatenablog.com

yamato8010.hatenablog.com

yamato8010.hatenablog.com