同期サブスクリプションの管理 - Kotlin SDK
項目一覧
- 前提条件
- サブスクリプションの概要
- オブジェクト タイプへのサブスクライブ
- 最初のサブスクリプション
- クライアント アプリでのサブスクリプションの管理
- このページの例について
- クエリにサブスクライブ
- クエリにサブスクライブ
- クエリ サブスクリプションの更新
- クエリ サブスクリプションが同期するまで待機する
- サブスクリプションの手動管理
- サブスクリプションを追加する
- サブスクリプションの変更が同期されるまで待機する
- サブスクリプション セットの状態
- 新しいクエリによるサブスクリプションの更新
- サブスクリプションの削除
- Flexible Sync RQL の要件と制限
- インデックス付きクエリ可能なフィールドのサブスクリプション要件
- Flexible Sync でサポートされていないクエリ演算子
- クエリをリストする
- 埋め込みオブジェクトまたはリンクされたオブジェクト
- クエリ サイズの制限
- パフォーマンスに関する考慮事項
- API 効率
- パフォーマンス向上のためのグループ更新
は、サブスクリプションと権限を使用して、アプリと同期するデータを決定します。 このページでは、Flexible Sync のサブスクライブを管理する方法について詳しく説明します。
詳しくは、App Services ドキュメントの「 Flexible Sync 」を参照してください。
前提条件
Flexible Sync サブスクライブを使用する前に、Device Sync を使用するようにアプリを設定し、バックエンドで Flexible Sync を構成する必要があります。
これを行うには、「 Device Sync をアプリに追加する 」手順で説明されている手順を実行します。
サブスクリプションの概要
バックエンドで Flexible Sync を構成するときは、クライアント アプリケーションがサブスクリプションを使用してクエリできるフィールドを指定します。
各サブスクリプションは、特定のオブジェクトタイプのクエリ可能なフィールドに対するクエリに対応します。 詳細については、App Services ドキュメントの「 クエリ可能なフィールド」を参照してください。
Realm はクエリ サブスクライブごとに、クエリに一致するデータを検索します。 ユーザーが適切な権限を持つサブスクリプションに一致するデータは、クライアントとバックエンド アプリケーション間で同期されます。
重要
Flexible SyncはRQLで利用可能なすべての演算子をサポートしていません。 詳細については、「 Flexible Sync RQL の制限」を参照してください。
オブジェクト タイプへのサブスクライブ
サブスクリプション セットはオブジェクトタイプに基づいています。 Realm オブジェクトのタイプが多い場合は、複数のサブスクリプションがあることがあります。 同じオブジェクトタイプに対して複数のサブスクライブを設定することもできます。
ただし、アプリ内でリンクされたオブジェクト、非対称オブジェクト、または地理空間データを使用する場合は、追加情報について次のセクションを参照してください。
リンクされたオブジェクト
アプリでリンクされたオブジェクト を使用する場合は、オブジェクト自体とそのリンクされたオブジェクトの両方をサブスクリプション セットに追加して、実際にリンクされたオブジェクトを確認する必要があります。
結果に含まれていないオブジェクトにリンクする プロパティを持つオブジェクトがサブスクライブ結果に含まれている場合、リンクは null に表示されます。 そのプロパティの値が null かどうか、またリンク先のオブジェクトが存在してもクエリ サブスクリプションの表示の対象外であるかどうかを区別する方法はありません。
非対称オブジェクト
アプリがData Ingestを使用して非対称オブジェクトを一方向に同期する場合、それらのオブジェクトのサブスクリプションを作成することはできません。 アプリが同じレルムに非対称オブジェクトと非対称オブジェクトを含む場合は、非対称オブジェクトの Flexible Sync サブスクリプション クエリを追加できます。
地理空間データ
バージョン 1.13.0 での変更: Atlas Device Sync でサポートされている地理空間データ
Kotlin SDK バージョン 1.13.0 以降では、地理空間クエリのサブスクリプションを作成できます。 古いバージョンの SDK で地理空間クエリをサブスクライブしようとすると、書き込み補正によるサーバー エラーが発生します。
詳細については、「地理空間データのクエリ 」を参照してください。
最初のサブスクリプション
Realm から読み取りまたは書込み (write) する前に、少なくとも 1 つのサブスクリプションが必要です。
クライアント アプリでのサブスクリプションの管理
クライアント アプリケーションでは、クエリ可能なフィールドの特定のクエリへのサブスクリプションを追加、更新、および削除します。 これにより、クライアント デバイスに同期されるデータが決まります。
ユーザーは次のアクションを実行できます。
任意のサブスクリプション名でサブスクリプションを追加する。
Kotlin SDK バージョン 1.10.0 以降では、
.subscribe()
を使用してRealmQuery
またはRealmResults
をサブスクライブできます。 これにより、サブスクライブが サブスクリプション セット に自動的に追加されます。subscriptions
API を使用してサブスクリプションセットにサブスクライブを手動で追加します。 パフォーマンスの最適化やビジネス ロジック上の理由で、サブスクリプションをより詳細に制御する必要がある場合は、この API を使用します。 詳細については、 「パフォーマンスに関する考慮事項」 セクションを参照してください。
Reactション状態に対応
新しいクエリでサブスクライブを更新する
オブジェクトタイプの個々のサブスクライブまたはすべてのサブスクライブを削除
このページの例について
このページの例では、タスク リスト アプリのデータセットを使用しています。
2 つの Realm オブジェクトタイプはTeam
とTask
です。
class Task : RealmObject { var _id: ObjectId = ObjectId() var taskName: String = "" var assignee: String? = null var completed: Boolean = false var progressMinutes: Int = 0 var dueDate: RealmInstant? = null } class Team : RealmObject { var _id: ObjectId = ObjectId() var teamName: String = "" var tasks: RealmList<Task>? = realmListOf() var members: RealmList<String> = realmListOf() }
このページの例では、承認されたユーザーと Flexible Sync SyncConfiguration()があることも前提としています。
// Login with authorized user and define a Flexible Sync SyncConfiguration val app = App.create(YOUR_APP_ID) val user = app.login(credentials) val flexSyncConfig = SyncConfiguration.Builder(user, setOf(Task::class, Team::class)) .initialSubscriptions { // Define the initial subscription set for the realm ... } .build() // Open the synced realm and manage subscriptions val realm = Realm.open(flexSyncConfig) Log.v("Successfully opened realm: ${realm.configuration}")
クエリにサブスクライブ
バージョン 1.10.0 の新機能。
サブスクリプション管理を簡素化するには、Realm Kotlin SDK バージョン1.10.0 実験的な.subscribe()を追加します RealmQuery
またはRealmResults
セットにサブスクライブするための API この API では、 サブスクリプションセット を通じてサブスクリプションを手動で追加および削除するの詳細が抽象化されます。
ユーザーは次のアクションを実行できます。
任意の名前のクエリを自動的にサブスクライブ
新しいクエリで名前付きサブスクライブを更新する
パフォーマンスの最適化やビジネス ロジック上の理由でサブスクライブをより制御する必要がある場合は、 subscriptions
API を使用してサブスクリプションセットを手動で管理できます。 詳細については、 「パフォーマンスに関する考慮事項」 セクションを参照してください。
クエリにサブスクライブ
クエリに.subscribe()
を付与して、特定のクエリに一致するオブジェクトのサブスクリプションを作成できます。
// Subscribe to a specific query val realmResults = realm.query<Task>("progressMinutes >= $0", 60) .subscribe() // Subscribe to all objects of a specific type val realmQuery = realm.query<Team>() realmQuery.subscribe()
これにより、名前のないサブスクリプションが作成され、 MutableSubscriptionSet
に追加されます。代わりに、サブスクリプションセットにサブスクリプションを手動で追加する必要があります。
名前付きのクエリにサブスクライブ
アプリが複数のサブスクライブで動作する場合、またはサブスクリプションを更新する場合は、クエリをサブスクライブするときに名前を追加することをお勧めします。 後でこの名前を使用して、サブスクリプションのクエリを更新したり、クエリを名前付きで削除したりできます。
サブスクライブに名前を追加するには、 .subscribe()
を呼び出すときに string を渡します。
// Add a subscription named "team_developer_education" val results = realm.query<Team>("teamName == $0", "Developer Education") .subscribe("team_developer_education")
クエリ サブスクリプションの更新
updateExisting
をtrue
に設定することで、名前付きクエリ サブスクリプションを新しいクエリで更新できます。
// Create a subscription named "bob_smith_teams" val results = realm.query<Team>("$0 IN members", "Bob Smith") .subscribe("bob_smith_teams") // Add another subscription with the same name with `updateExisting` set to true // to replace the existing subscription val updateResults = realm.query<Team>("$0 IN members AND teamName == $1", "Bob Smith", "QA") .subscribe("bob_smith_teams", updateExisting = true)
これにより、サブスクリプションセット内のサブスクリプションを手動で更新する必要がある代わりに、サブスクリプションが自動的に更新されます。
クエリ サブスクリプションが同期するまで待機する
クエリの結果セットをサブスクライブする場合、そのセットには同期されるまでオブジェクトが含まれません。 アプリが オブジェクトを作成する場合、ユーザーが同期データを操作する前に同期データをダウンロードする必要がない場合があります。 ただし、ユーザーが操作する前にサーバーからのデータが必要な場合は、アプリが同期するまで待機するように指定できます。 これにより、サーバーからデータが同期されるまでアプリの実行がブロックされます。
val results = realm.query<Team>("$0 IN members", "Bob Smith") .subscribe("bob_smith_teams", updateExisting = false, WaitForSync.ALWAYS) // After waiting for sync, the results set contains all the objects // that match the query - in our case, 1 println("The number of teams that have Bob Smith as a member is ${results.size}")
このオプションでは、 WaitForSync列挙型が使用されます。その値は次のとおりです。
FIRST_TIME
:(デフォルト)アプリが最初にサブスクリプションを作成したときに、一致するオブジェクトをダウンロードするまで待機します。 それ以外の場合は、新しいダウンロードを待たずに戻ります。 サブスクリプションを最初に追加するときに、アプリはインターネットに接続する必要があります。 オプションで、timeout
値を指定できます。ALWAYS
:.subscribe()
メソッドが呼び出されるたびに一致するオブジェクトをダウンロードするまで待機します。 アプリはデータをダウンロードするには、インターネット接続が必要です。 オプションで、timeout
値を指定できます。NEVER
: 一致するオブジェクトがダウンロードされるのを待たない。 アプリは、アプリが初めて起動するときに認証するためにインターネット接続を必要としますが、キャッシュされた認証情報を使用して以降の起動ではオフラインで開くことができます。
サブスクリプションの手動管理
クライアント アプリケーションで、 subscriptions
API を使用してサブスクリプションのセットを手動で管理します。 この API を使用すると、クエリ可能なフィールドに対する特定のクエリを追加、更新、または削除できます。 これらのクエリによって、クライアント デバイスに同期されるデータが決定されます。
Kotlin SDK バージョン1.10.0以降では、 .subscribe() APIを使用してサブスクリプションを自動的に追加できます。 この API は、 RealmQuery
またはRealmResults
からMutableSubscriptionSet
に直接サブスクリプションを追加します。
サブスクリプションを追加する
名前を付けないサブスクリプションまたは名前付きサブスクリプションを追加できます。
Tip
サブスクリプション名の指定
アプリケーションで複数のサブスクライブを使用する場合は、常にサブスクリプション名を指定します。 これにより、アプリ内の他の場所でサブスクライブを検索、更新、削除することが簡単になります。
サブスクリプションを手動で作成するには、 サブスクリプション更新ブロック にサブスクライブを追加します。 新しいサブスクリプションはそれぞれ、クライアントの Realm サブスクリプションに追加します。
realm.subscriptions.update { add( realm.query<Task>("progressMinutes >= $0",60) ) }
サブスクリプションを作成するときに、サブスクリプション名を指定することもできます。
// Add a subscription named "team_dev_ed" realm.subscriptions.update { realm -> add( realm.query<Team>("teamName == $0", "Developer Education"), name = "team_dev_ed" ) }
重要
オブジェクト リンク
リンクされたオブジェクトを表示するには、オブジェクトとそのリンクされたオブジェクトの両方をサブスクリプション セットに追加する必要があります。
結果に含まれていないオブジェクトにリンクする プロパティを持つオブジェクトがサブスクライブ結果に含まれている場合、リンクは null に表示されます。 そのプロパティの値が null かどうか、またはリンク先のオブジェクトが存在するものの、サブスクライブが欠落しているためクライアントで使用できないかどうかを区別する方法はありません。
初期サブスクリプションで Realm をブートストラップする
Realm から読み取りまたは書込み (write) する前に、少なくとも 1 つのサブスクリプションが必要です。 SyncConfiguration()を使用してRealmを開くと、初期サブスクリプションセットでRealmをブートストラップできます。 詳細については、「 同期された Realm のオープン」を参照してください。
Realm のブートストラップに使用するサブスクライブ クエリを含むinitialSubscriptions
パラメーターを渡します。
// Bootstrap the realm with an initial query to subscribe to val flexSyncConfig = SyncConfiguration.Builder(user, setOf(Team::class, Task::class)) .initialSubscriptions { realm -> add( realm.query<Team>("$0 IN members", "Bob Smith"), "bob_smith_teams" ) } .build()
アプリを起動するたびにこの初期サブスクリプションを再実行する必要がある場合は、次の追加のパラメータを渡すことができます: rerunOnOpen
。 これは、アプリを起動するたびに初期サブスクリプションを再実行するかどうかを示すブール値です。 動的時間範囲やサブスクライブの静的変数の再計算が必要なその他のクエリを再実行するには、この操作が必要になる場合があります。
この例では、不完全なタスクのみが必要です。 rerunOnOpen
をtrue
に設定すると、アプリを起動するたびに、クエリは目的のクエリ結果に基づいて同期する関連オブジェクトを動的に再計算します。
// `rerunOnOpen` lets the app recalculate this query every time the app opens val rerunOnOpenConfig = SyncConfiguration.Builder(user, setOf(Team::class, Task::class)) .initialSubscriptions(rerunOnOpen = true) { realm -> add( realm.query<Team>("completed == $0", false) ) } .build()
サブスクリプションの変更が同期されるまで待機する
サブスクリプション セットへの更新をローカルに書き込むことは、サブスクリプション変更の 1 つの要素のみです。 ローカル サブスクリプションの変更後、クライアントはサーバーと同期して、サブスクリプションの変更によるデータの更新を解決します。 これは、同期された Realm からデータを追加または削除することを意味します。
SyncConfiguration.waitForInitial remoteData()の使用 ビルダ メソッドを使用して、Realm を開く前に、クライアント サブスクリプション データがバックエンドに同期されるまでアプリケーションを強制的にブロックします。
// Update the list of subscriptions realm.subscriptions.update { add( realm.query<Team>("$0 IN members", "Jane Doe"), "jane_doe_teams" ) } // Wait for subscription to fully synchronize changes realm.subscriptions.waitForSynchronization(Duration.parse("10s"))
また、 SubscriptionSet.waitForSynchronization()を使用して、同期接続をインスタンス化した後、サブスクライブ同期が完了するまで実行を遅延させることもできます。
サブスクリプション セットの状態
サブスクリプションセットの現在の状態を読み取るには、 SubscriptionSet.rateプロパティを使用します。
SUPERCEDED
(旧 状態がSUPERCEDED
になった場合は、サブスクライブセットの新しいインスタンスを取得した後に、サブスクライブセットに書き込む必要があります。
注意
サブスクリプション状態「完了」
サブスクリプションセットの状態「完了」は、「同期が実行された」または「すべてのドキュメントが同期された」を意味するものではありません。 「完了」とは、次の 2 つの処理が発生したことを意味します。
サブスクライブは、現在サーバーと同期されているアクティブなサブスクリプションセットになりました。
サブスクリプションがサーバーに送信されたときにサブスクリプションに一致したドキュメントは、現在、ローカルデバイス上にあります。 これには、現在サブスクリプションに一致しているすべてのドキュメントが必ずしも含まれるわけではないことに注意してください。
Realm SDK には、サブスクリプションに一致するすべてのドキュメントがデバイスに同期されているかどうかを確認する方法は提供されていません。
新しいクエリによるサブスクリプションの更新
SubscriptionSet.update() を使用してサブスクライブを更新できます。
この例ではMutableSubscriptionSet.add()を使用します。 "bob_smith_teams"
という名前のサブスクライブのクエリを更新します。 add()
でサブスクリプションを更新するには、 updateExisting
パラメータをtrue
に設定する必要があります。
// Create a subscription named "bob_smith_teams" realm.subscriptions.update { add( realm.query<Team>("$0 IN members", "Bob Smith"), "bob_smith_teams" ) } // Set `updateExisting` to true to replace the existing // "bob_smith_teams" subscription realm.subscriptions.update { add( realm.query<Team>("$0 IN members AND $1 IN members", "Bob Smith", "Jane Doe"), "bob_smith_teams", updateExisting = true ) }
名前なしで作成されたサブスクライブを更新することはできません。 ただし、クエリで名前のないサブスクリプションを検索してサブスクライブセットから削除し、更新されたクエリで新しいサブスクリプションを追加することはできます。
// Search for the subscription by query val subscription = realm.subscriptions.findByQuery( realm.query<Team>("teamName == $0", "Developer Education") ) // Remove the returned subscription and add the updated query if (subscription != null) { realm.subscriptions.update { remove(subscription) add( realm.query<Team>("teamName == $0", "DevEd"), "team_developer_education" ) } }
サブスクリプションの削除
サブスクリプションを削除するには、次の方法があります。
1 つのサブスクライブ クエリを削除
特定のオブジェクトタイプへのすべてのサブスクライブを削除
すべてのサブスクライブを削除
名前のないサブスクライブをすべて削除します
サブスクリプション クエリを削除すると、Realm はクライアント デバイスからクエリに一致した同期データを非同期に削除します。
1 つのサブスクリプションを削除
MutableSubscriptionSet.remove()を使用して、特定のサブスクライブ クエリを削除できます。 名前でサブスクライブを検索してから、返されたサブスクライブをremove()
に渡すか、サブスクリプション名をremove()
に直接渡すことができます。
realm.subscriptions.update { add( realm.query<Team>("$0 IN members", "Bob Smith"), "bob_smith_teams" ) } // Wait for synchronization to complete before updating subscriptions realm.subscriptions.waitForSynchronization(Duration.parse("10s")) // Remove subscription by name realm.subscriptions.update { remove("bob_smith_teams") }
オブジェクト タイプへのすべてのサブスクリプションを削除
特定のオブジェクトタイプへのすべてのサブスクライブを削除する場合は、 クラスをMutableSubscriptionSet.removeAll()に渡します。 メソッド:
realm.subscriptions.update { add( realm.query<Team>("$0 IN members", "Bob Smith"), "bob_smith_teams") } // Wait for synchronization to complete before updating subscriptions realm.subscriptions.waitForSynchronization(Duration.parse("10s")) // Remove all subscriptions to type Team realm.subscriptions.update { removeAll(Team::class) }
すべてのサブスクリプションを削除
サブスクリプションセットからすべてのサブスクリプションを削除するには、 MutableSubscriptionSet.removeAll()を使用します。 引数がない場合は次のとおりです。
警告
すべてのサブスクライブを削除し、新しいサブスクライブを追加しないと、 エラーが発生します。 柔軟な同期構成で開かれたRealmでは、サーバーと同期するために少なくとも 1 つのサブスクライブが必要です。
// Remove all subscriptions realm.subscriptions.update { removeAll() }
すべての名前のないサブスクリプションを削除
バージョン 1.10.0 の新機能。
一時的な、または動的に生成される名前のないサブスクリプションは削除するが、名前付きサブスクリプションはその場で残すしたい場合があります。
次のように、 removeAll
メソッドを呼び出すときにanonymousOnly
をtrue
に設定することで、名前のない(匿名)サブスクリプションをサブスクリプションセットからすべて削除できます。
// Remove all unnamed (anonymous) subscriptions realm.subscriptions.update { removeAll(anonymousOnly = true) }
Flexible Sync RQL の要件と制限
インデックス付きクエリ可能なフィールドのサブスクリプション要件
インデックス付きのクエリ可能なフィールドをアプリに追加すると、厳密にパーティション化されたデータに対する単純なクエリのパフォーマンスが向上します。 たとえば、クエリがデバイス、ストア、またはユーザーにデータを厳密にマッピングするアプリuser_id == $0, “641374b03725038381d2e1fb”
など)は、インデックス付きクエリ可能なフィールドの候補となります。 ただし、インデックス付きのクエリ可能なフィールドには、クエリ サブスクリプションで使用するための特定の要件があります。
インデックス付きクエリ可能なフィールドは、すべてのサブスクライブ クエリで使用する必要があります。 クエリから欠落することはできません。
インデックス付きクエリ可能なフィールドは、サブスクライブ クエリで少なくとも 1 回、定数に対して
==
またはIN
の比較を使用する必要があります。 たとえば、user_id == $0, "641374b03725038381d2e1fb"
やstore_id IN $0, {1,2,3}
などです。
オプションとして、インデックス付きクエリ可能なフィールドが==
またはIN
を少なくとも 1 回使用して定数と直接比較される限り、 AND
比較を含めることができます。 たとえば、 store_id IN {1,2,3} AND region=="Northeast"
やstore_id == 1 AND (active_promotions < 5 OR num_employees < 10)
などです。
インデックス付きクエリ可能なフィールドに対する無効なFlexible Sync クエリには、次のクエリが含まれます。
インデックス付きクエリ可能なフィールドは、クエリの残りの部分で
AND
を使用しません。store_id IN {1,2,3} OR region=="Northeast"
OR
たとえば、AND
は ではなく を使用しているため無効です。同様に、store_id == 1 AND active_promotions < 5 OR num_employees < 10
は無効です。AND
はクエリ全体ではなく、その横にあるタームにのみ適用されるためです。インデックス付きクエリ可能なフィールドは 等価演算子 では使用されません。 たとえば、
store_id > 2 AND region=="Northeast"
は無効です。インデックス付きクエリ可能なフィールドでは>
演算子のみが使用され、等価比較がないためです。クエリに、インデックス付きのクエリ可能なフィールドが完全にありません。 たとえば、
region=="Northeast
またはtruepredicate
は、インデックス付きクエリ可能なフィールドが含まれていないため無効です。
Flexible Sync でサポートされていないクエリ演算子
RQL 演算子を使用する場合、Flexible Sync にはいくつかの制限があります。 同期するデータを決定するクエリ サブスクリプションを書込む場合、サーバーはこれらのクエリ演算子をサポートしていません。 ただし、RQL 機能の全範囲を使用して、クライアント アプリケーション内の同期されたデータセットをクエリすることはできます。
演算子タイプ | サポートされていない演算子 |
---|---|
集計演算子 | @avg , @count , @max , @min , @sum |
クエリサフィックス | DISTINCT , SORT , LIMIT |
大文字と小文字を区別しないクエリ( [c]
)は、インデックスを効果的に使用できません。 その結果、大文字と小文字を区別しないクエリはパフォーマンスの問題を引き起こす可能性があるため、推奨されません。
Flexible Sync は、配列フィールドの@count
のみをサポートします。
クエリをリストする
Flexible Sync は、 IN
演算子を使用するクエリ リストをサポートしています。
定数のリストをクエリして、クエリ可能なフィールドの値が含まれているかどうかを確認できます。
// Query a constant list for a queryable field value "priority IN { 1, 2, 3 }"
クエリ可能なフィールドに配列値がある場合は、定数値が含まれているかどうかをクエリできます。
// Query an array-valued queryable field for a constant value "'comedy' IN genres"
警告
Flexible Sync クエリでは、2 つのリストを相互に比較することはできません。 RQLこれはFlexible Sync クエリの外部では有効な 構文であることに注意してください。
// Invalid Flexible Sync query. Do not do this! "{'comedy', 'horror', 'suspense'} IN genres" // Another invalid Flexible Sync query. Do not do this! "ANY {'comedy', 'horror', 'suspense'} != ANY genres"
埋め込みオブジェクトまたはリンクされたオブジェクト
Flexible Sync は、 埋め込みオブジェクトまたはリンク のプロパティに対するクエリをサポートしていません。 たとえば、 obj1.field == "foo"
。
クエリ サイズの制限
サブスクリプションセット内の特定のクエリ サブスクライブのサイズ制限は256 kBです。 この制限を超えると、 LimitsExceeded エラー が発生します。
パフォーマンスに関する考慮事項
API 効率
「クエリへのサブスクライブ」セクションで説明されている.subscribe()
API を使用して複数のサブスクリプションを管理する場合、 サブスクリプション セット API を通じてサブスクリプションを手動で管理する場合、バッチ更新を実行するより効率が低くなります。 複数のサブスクリプション変更を行う際のパフォーマンスを向上させるには、「サブスクリプションの手動管理」セクションで説明されているsubscriptions.update
API を使用します。
パフォーマンス向上のためのグループ更新
サブスクリプションセットのすべての書込みトランザクション (write transaction) にはパフォーマンス コストがかかります。 セッション中に Realm オブジェクトを複数更新する必要がある場合は、すべての変更が完了するまで編集されたオブジェクトをメモリ内に保持することを検討してください。 これにより、すべての変更ではなく、完全で更新されたオブジェクトのみが Realm に書き込まれるため、同期のパフォーマンスが向上します。