RxSwift_v1.0ノート——21 RxRealm

5679 ワード

RxSwift_v1.0ノート——21 RxRealm


昔、遠い平行宇宙では、開発者がappを開発するにはデータベースが必要でした.一般的だがうるさいCore Dataを選択したり、SQLiteのカスタムパッケージを作成したりすることができます.その後Realmが現れ、アプリケーションでデータベースを突然使用することが容易になりました.
Realmのデータベースクエリーは「live」です.結果セットの内容は、データベースの変更とともに更新されます.アイテムを挿入、変更または削除すると、「結果」オブジェクトの変更がすぐに表示されます.さらに、微細度(fine-grained)通知は、Resultsオブジェクトでの変更の詳細を提供します.
Listタイプも同様で、使用中の単一オブジェクトでも自動的に更新されるオブジェクトセットを構築し、データベースを変更する必要があります.これらのすべてはRealmをこれらの動的変化をobservableシーケンスに暴露する理想的な候補にした!
RxRealm, https://github.com/RxSwiftCommunity/RxRealm、RxSwiftCommunity組織の下にあるもう一つのプロジェクトです.その目標は、Realmをレスポンスプロセスにシームレスに統合することです.

Auto-updating results 343


データベース・クエリーは、オブジェクトのセットを定義します.最も基本的なレベルでは、RxRealmパッケージの結果はobservableであり、初期コンテンツとともにトリガーされ、セットが変更されるたびに再び発生します.
let realm = try! Realm()
let result = realm.objects(MyObject.self)
Observable.collection(from: result)
  .subscribe(onNext: { items in
    print("Query returned \(items.count) items")
  })
  .addDisposableTo(disposeBag)

データベースに変更をコミットするたびに、結果に影響し、コレクションが再びトリガーされます.

Arrays 344


Realm集合の代わりに配列を取得するのは簡単です.
let result = realm.objects(MyObject.self)
Observable.array(from: result)
  .subscribe(onNext: { array in
    print("Query returned \(array.count) items")
  })
  .addDisposableTo(disposeBag)
Note:                   ,                        。 collection(from:)         。

Asynchronous first item 344


Observable.collection(from:) and Observable.array(from:)は、初期アイテムのセットまたは配列を同期して送信します.このときobservable(subscribe(:)関数が戻る前に購読し、最初の要素を受信します.これは、特にユーザーインタフェースを起動すると、アプリケーションに干渉します.一般的なエラーソースの1つは、次のコードが実行されたと仮定することです.ただし、最初の要素にsubscribe(:)が書かれていません.
幸いなことに、2つの関数は実際に2番目のパラメータを受信し、デフォルトはtrueです.実際の署名はObservableです.collection(from:synchronousStart:) and Observable.array(from:synchronousStart:).
最初の要素を非同期で送信したい場合は、非同期フラグビットにfalseを渡します.
let result = realm.objects(MyObject.self)
Observable.array(from: result, synchronousStart: false)
  .subscribe(onNext: { array in
    print("Query returned \(array.count) items")
  })
  .addDisposableTo(disposeBag)

初期Realm通知がトリガーされると、初期コンテンツが受信されます.

変更セット345


RxRealmは、より複雑なobservablesにアクセスできます.結果が更新されたときにRealmから通知されたchangesetsを取得するにはObservableを使用します.changeset(from:synchronizedStart:).このobservableは元の結果の集合とともにchangesetを送信する
let result = realm.objects(MyObject.self)
Observable.changeset(from: result)
  .subscribe(onNext: { results, changes in
  if let changes = changes {
      // it's an update
      print("deleted: \(changes.deleted)")
      print("inserted: \(changes.inserted)")
      print("updated: \(changes.updated)")
    } else {
      // it's the initial data
    print(results)
    }
  }
  .addDisposableTo(disposeBag)

Observable.ArrayWithChangeset(from:synchronizedStart:)は、このAPIのバリエーションであり、配列のobservableとRealm ChangeSetを返します.

Single objects 345


RxRealmの最終的な特性は、単一のオブジェクトを観察し、データベース内で更新するたびに新しいオブジェクトを得ることができます.たとえば、データベース内のオブジェクトにユーザー設定を格納する場合は、コード内の変化の位置で観察して設定の変化を自動的に更新します.
Realmモバイルプラットフォームを使用している場合は、他のデバイスからのアクティビティの更新が特に簡単です.
let hideCompletedObs = Observable.from(object: preferencesObject)
  .map { prefs -> Bool in prefs.hideCompletedTodos }
  .distinctUntilChanged()
let todosObs = realm.objects(Todo.self)
Observable.combineLatest(hideCompletedObs, todosObs) {
  hideCompleted, todos in
  if hideCompleted {
    return todos.filter { $0.completed == false }
  }
  return todos
  }
  .bindTo(tableView.rx.items) {
    (tableView: UITableView, index: Int, element: Todo) in
    // return cell here
  }
  .addDisposableTo(disposeBag)

この場合、アプリケーションには、最初にリフレッシュされ、ユーザープリファレンスのhide completed todosフラグが変更される保留中のリストが表示されます.
(in case)オブジェクトの特定の属性の変化にのみ興味がある場合は、Observableを使用します.propertyChanges(object:)は、各属性の変更イベントを購読します.上記のtodoアプリケーションシーンでは、次のように、特定のタスクのタイトルの変更を観察したい場合があります.
Observable.propertyChanges(object: task)
  .filter { $0.name == "taskTitle" }
  .subscribe(onNext: { change in
    print("property \(change.name) changed from: \(change.oldValue) to: \
      (change.newValue)")
  })
  .addDisposableTo(bag)

Adding objects 346


RxRealmはadd()and delete()観察者を用いてRealmクラスを拡張した.これらを使用して、プロジェクトの追加または削除のシーケンスを観察することができます.シーケンスがオブジェクトを送信するたびに、データベースから自動的に追加または削除できます.
このシナリオを考慮すると、特定の間隔で新しいメッセージに対してリモートサーバをクエリーする必要があります.APIが新しいメッセージを返すと、メッセージがデータベースに追加されます(RxRealmを使用してデータベース変更のメッセージリストを自動的に更新します):
Observable
  .timer(0, period: 60, scheduler: MainScheduler.instance)
  .flatMap { _ -> Observable in
    let messages = realm.objects(Messages.self).sorted(byProperty:
      "dateReceived")
    if let lastMessage = messages.last {
      return MailAPI.newMessagesSince(lastMessage.dateReceived)
    }
    return MailAPI.newMessagesSince(Date.distantPast)
  }
  .subscribe(realm.rx.add())
  .addDisposableTo(disposeBag)

タイマによって送信された値は単純に無視され、最後にメッセージを受信した日付以降のすべての情報が要求され、結果がRxRealmに伝達される.
realmオブジェクトでadd()を使用する場合は注意してください.RxRealmは、Realmデータベースオブジェクトを継続的にサブスクリプションに保持します.Realmオブジェクトを保持したくない場合は、独自の変更版:Realmを使用します.rx.add() or Realm.rx.add(configuration:):この静的メソッドは、現在のスレッドに存在するRealmエンティティをキャプチャし、維持して使用する必要はありません.

Deleting objects 347


同様のエンドポイント(endpoint)を使用すると、データベースから存在するオブジェクトまたはオブジェクトのセットを削除できます.
let realm = try! Realm()
deleteSelectedMessagesButton.rx.tap
  .map { self.selectedMessages() }
  .bindTo(realm.rx.delete())
  .addDisposableTo(disposeBag)

再度、Realmオブジェクトは、サブスクリプションの全期間保持されます.