CRUD - Swift SDK
書込みトランザクション (write transaction)
Realm は高効率のストレージ エンジンを使用してオブジェクトを永続化します。 Realm でオブジェクトを作成し、Realm 内のオブジェクトを更新し、最終的に Realm からオブジェクトを削除することができます。 これらの操作は Realm の状態を変更するため、書込み (write) と呼びます。
Realm はトランザクション単位で書込み (write) を処理します。 トランザクションは 、Realm が単一の分割不可の操作として取り扱う読み取り操作と書込み (write) 操作のリストです。 言い換えれば、トランザクションはすべてであるか、または何もなかったようになります。つまり、トランザクション内のすべての操作が成功するか、トランザクション内のどの操作が有効になりません。
すべての書込み (write) はトランザクション内で発生する必要があります。
Realm では一度に 1 つのトランザクションのみを開くことができます。 Realm は、開いているトランザクションが完了するまで、他のスレッドへの他の書込みをブロックします。 その結果、トランザクション内で Realm から値を読み取るときに競合状態は発生しません。
トランザクションが完了すると、Realm はトランザクションをコミットまたはキャンセルします。
Realm がトランザクションをコミットすると、Realm はすべての変更をディスクに書込みます。 同期された Realm の場合、SDK は Atlas Device Sync との同期のために変更をキューに入れます。
Realm が書込みトランザクションをキャンセルするか、トランザクション内の操作によってエラーが発生すると、すべての変更は破棄されます(または「ロールバック」)。
トランザクションの実行
Swift SDK は、0 個以上の読み取りおよび書込み (write) 操作を含むコールバック関数として各トランザクションを表します。 トランザクションを実行するには、トランザクション コールバックを定義し、それを Realm の write
メソッドに渡します。 このコールバック内では、Realm の作成、読み取り、アップデート、および削除を無料で実行できます。 Realm が実行時にコールバック内のコードが例外をスローした場合、Realm はトランザクションをキャンセルします。 それ以外の場合、Realm はコールバックの後にトランザクションをコミットします。
重要
同時実行性保証
トランザクションは相互にブロックされるため、UI スレッドとバックグラウンド スレッドの両方でトランザクションを開始しないようにすることをお勧めします。 Syncを使用している場合は、Realm がバックグラウンド スレッドで同期を処理するため、UI スレッドでトランザクションを開始することは完全に避けてください。 バックグラウンド トランザクションによって UI スレッドのトランザクションがブロックされると、アプリが応答しなくなることがあります。
例
次のコードは、Realm の書込み (write) メソッドを使用してトランザクションを実行する方法を示しています。 コールバックのコードが例外をスローした場合、Realm はトランザクションをキャンセルします。 それ以外の場合、Realm はトランザクションをコミットします。
// Open the default realm. RLMRealm *realm = [RLMRealm defaultRealm]; // Open a thread-safe transaction. [realm transactionWithBlock:^() { // ... Make changes ... // Realm automatically cancels the transaction in case of exception. // Otherwise, Realm automatically commits the transaction at the // end of the code block. }];
// Open the default realm. let realm = try! Realm() // Prepare to handle exceptions. do { // Open a thread-safe transaction. try realm.write { // Make any writes within this code block. // Realm automatically cancels the transaction // if this code throws an exception. Otherwise, // Realm automatically commits the transaction // after the end of this code block. } } catch let error as NSError { // Failed to write to realm. // ... Handle error ... }
インターフェース駆動型書込み
Realm は常に通知を非同期に配信するため、UI スレッドをブロックすることはありません。 ただし、UI に変更を即座に反映する必要がある状況もあります。 書き込みと同時に UI を直接更新すると、最終通知はその更新をdoubleにする可能性があります。 これにより、UI とバッキング データ ストア間の状態が一致しないため、アプリがクラッシュする可能性があります。 これを回避するには、特定のハンドラーに通知を送信せずに書き込みます。 このタイプのトランザクションはインターフェース駆動型書込みと呼ばれます。
例
アプリの設計では UI によるテーブルアップデートへの即座の応答が必要なため、テーブル ビューのデータソースを手動で管理することにしたとします。 ユーザーがテーブル ビューに項目を追加するとすぐに、それをデータソースに挿入します。これにより、Realm に書込まれますが、アニメーションもすぐに開始されます。 ただし、Realm がこの挿入の変更通知を少しあとに送信すると、オブジェクトが追加されたことを示します。 ただし、テーブル ビューはすでに更新されています。 この場合を処理するための複雑なコードを記述するのではなく、インターフェース駆動型書込み (write) を使用して、その書込み (write) に対して特定の通知ハンドラーが起動するのを防ぐことができます。
インターフェース駆動型書込み(サイレント書込みとも呼ばれる)は、同期された Realm できめ細かなコレクション通知を使用する場合に特に便利です。 現在のユーザーの更新にインターフェースベースの書込み (write) を使用し、UI をすぐに更新しますが、同期プロセスでは標準の通知を使用して UI を更新できます。