RealmとRxSwiftを組み合わせた拡張ライブラリRealmX
RealmXとは
(※Github Link Card Creatorで作成しました。ありがとうございます!)
RealmとRxSwiftを使い、DBの状態をRxのストリームに乗せて監視するマイクロライブラリです。
RealmXを使うと何ができるのか
二つの機能を提供しています。
DBのレコードをRxのストリームに乗せて監視する
DBの値が更新されたら画面を更新する。などの操作が簡単に書けます。Realmに対して処理を行い、
completable
を返す
Rxのストリームの中でRealmを簡単に操作できます。
インストール方法
cocoapods
podfileに以下を書いてください。
pod 'Realm-rX'
その後pod update
することでインストール完了です。
carthage
Cartfileに以下を書いてください。
github "Urotea/RealmX"
その後carghage update
することでインストール完了です。
DBのレコードを監視する
RxSwiftとRealmを使ってアプリを作っていると、DBのレコードの更新をObservable
で流したくなります。
Realmはレコードの変更を検知する機能を持っているので、それをRxSwiftでラップしました。
本ライブラリを導入すると、以下のように書くことができます。
// バックグラウンドでも動くというパフォーマンス
DispatchQueue.global(qos: .background).async {
autoreleasepool {
let realm = try! Realm()
realm.objects(Dog.self)
.toObservable() // 本ライブラリで提供するAPI
.subscribe {
print($0)
}
}
}
上記のコードのtoObservable()
がこのライブラリが提供するメソッドです。
Realm内のDogの状態が変更された時(新しいデータの追加、削除、変更)ストリームが発火します。
ストリームに乗せてRealmを操作する
Realmの操作を非同期で実行して、完了したら通知を受け取りたい時があります。
doInTransaction(objtrct:){}
はそれを支援します。
let realm = try! Realm()
let dog = Dog()
dog.age = 1
realm.doInTransaction(object: [dog]) { (realm: Realm, dogList: [Dog]) in
realm.add(dogList.first!)
}.subscribe(onCompleted: {
print("insert success.")
})
ここではadd
していますが、delete
など、他の操作を行うこともできます。
また以下のように、Realmインスタンスの生成スレッドと、ストリームのスレッドが異なっても動くようになっています。
let realm = try! Realm()
let dog = Dog()
dog.age = 1
realm.doInTransaction(object: [dog]) { (realm: Realm, dogList: [Dog]) in
realm.add(dogList.first!) // ここの実行スレッドはsubscribeOnで指定したスレッド
}.subscribeOn(/* どこかのスレッド */)
.subscribe(onCompleted: {
print("insert success.")
})
使い方のススメ(toObservable)
Realmでは、可能な限りResultsで取り出す範囲を絞り込むことが無駄なI/Oを減らすコツです。
RealmのResultsに対する操作は高速に動作します。しかし、Resutlsから値を取り出すときにはそれなりの時間がかかります。
let realm = try! Realm()
realm.objects(Dog.self).filter("age > 2").toObservable().subscribe{}
このように記述することで、2才以上のDogのみ監視対象とすることができます。
また、toObservable()
の返り値もResultsなので、そこでさらなる絞り込みを行うことも可能です。
とにかく、できる限りResultsで数を絞り込むことがRealmを高速に動作させるコツです。
本ライブラリはResultsをストリームで管理することで、支援します。
スレッドに関する注意
本ライブラリを使用するときにスレッドに関して2点注意する必要があります。
toObservable()
は必ずメインスレッドでストリームを流してくる
RealmはDBのレコードを監視するときにrunloop
を必要とします。基本的にこれはメインスレッドのみ持つので、監視はメインスレッドで行なっています。それにより、toObservable()
もメインスレッドでストリームを流します。
- RealmのResultsはスレッドを超えられない
RealmのResultsはスレッドを越えることができません。(参考)
RxのオペレータであるobserveOn
をResultsを引き渡す場所に挟むとエラーが発生します。これはRealmの制約です。
let realm = try! Realm()
realm.objects(Dog.self).toObservable() // メインスレッドでストリームを流す
.observeOn(/* どこかのスレッド */) // これはエラーを吐く
.subscribe{}
ですので、もしバックグラウンドスレッドに持って行く場合は、Resultsから値を取り出すことでスレッドを越えることができます。
let realm = try! Realm()
realm.objects(Dog.self).toObservable() // メインスレッドでストリームを流す
.map{ results -> DogStruct in /* ResultsからStructにmapする */}
.observeOn(/* どこかのスレッド */)
/* 何かしらの処理 */
.subscribe{}
最後に
モバイルアプリはUIスレッドをブロックしないように気を付けないと簡単に画面が固まってしまいます。
あらゆるイベントをストリームに流してレッツリアクティブ。
(あと祝!初OSS)
Author And Source
この問題について(RealmとRxSwiftを組み合わせた拡張ライブラリRealmX), 我々は、より多くの情報をここで見つけました https://qiita.com/Urotea/items/058e018dfc2352c81132著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .