Reactに対応する - C++ SDK
すべての Realm オブジェクトはライブ オブジェクトであるため、変更されるたびに自動的に更新されます。 Realm は、プロパティが変更されるたびに通知イベントを発行します。 通知ハンドラーを登録してこれらの通知イベントをリッスンし、最新データで UI を更新できます。
オブジェクト変更リスナーの登録
Realm 内の特定のオブジェクトに通知ハンドラーを登録できます。 Realm はハンドラーに次のように通知します。
オブジェクトが削除された場合。
オブジェクトのプロパティのいずれかが変更された場合。
auto token = object.observe([&](auto&& change) { ... }
ハンドラーは、オブジェクトが削除されたかどうかなど、変更に関する情報を含む object_changeオブジェクトを受け取ります。 これには、変更されたフィールドの情報、それらのフィールドの新しい値(List プロパティを除く)、およびフィールドの古い値が含まれる場合があるプロパティ変更オブジェクトのリストが含まれる場合があります。
if (change.error) { rethrow_exception(change.error); } if (change.is_deleted) { std::cout << "The object was deleted.\n"; } else { for (auto& propertyChange : change.property_changes) { std::cout << "The object's " << propertyChange.name << " property has changed.\n"; auto newPropertyValue = std::get<std::string>(*propertyChange.new_value); std::cout << "The new value is " << newPropertyValue << "\n"; } }
変更を加えると、 refresh()はRealmを更新して通知を発行します。
auto config = realm::db_config(); auto realm = realm::db(std::move(config)); // Create an object and move it into the database. auto dog = realm::Dog{.name = "Max"}; realm.write([&] { realm.add(std::move(dog)); }); auto dogs = realm.objects<realm::Dog>(); auto specificDog = dogs[0]; // Set up the listener & observe object notifications. auto token = specificDog.observe([&](auto&& change) { try { if (change.error) { rethrow_exception(change.error); } if (change.is_deleted) { std::cout << "The object was deleted.\n"; } else { for (auto& propertyChange : change.property_changes) { std::cout << "The object's " << propertyChange.name << " property has changed.\n"; auto newPropertyValue = std::get<std::string>(*propertyChange.new_value); std::cout << "The new value is " << newPropertyValue << "\n"; } } } catch (std::exception const& e) { std::cerr << "Error: " << e.what() << "\n"; } }); // Update the dog's name to see the effect. realm.write([&] { specificDog.name = "Wolfie"; }); // Deleting the object triggers a delete notification. realm.write([&] { realm.remove(specificDog); }); // Refresh the database after the change to trigger the notification. realm.refresh(); // Unregister the token when done observing. token.unregister();
コレクション変更リスナーの登録
コレクションに通知ハンドラーを登録できます。 コレクションは、プリミティブやその他のオブジェクトを含む、サポートされている データ型を含めることができるリスト、マップ、またはセットのプロパティです。
Realm は、書込みトランザクションによってコレクション内のオブジェクトが削除、追加、または変更されるたびにハンドラーに通知します。
通知は、3 つのインデックスのリスト(削除、挿入、および変更されたオブジェクトのインデックス)を使用して前回の通知以降の変更を説明します。
重要
順序は重要
コレクション通知ハンドラーでは、削除、挿入、変更の順に常に変更を適用します。 削除前に挿入を処理すると、予期しない動作が発生する可能性があります。
コレクション通知では、削除、追加、または変更されたオブジェクトのインデックスを報告するcollection_change構造体が提供されます。 コレクションが削除されたかどうかを通知することもできます。
この例では、 Person
オブジェクトには プロパティとしてDog
オブジェクトのリストがあります。
struct Person { std::string name; std::vector<Dog*> dogs; }; REALM_SCHEMA(Person, name, dogs)
犬を排除したり、新しい犬を追加したり、犬を変更したりすると、通知ハンドラーがトリガーされます。
// Set up the listener & observe a collection. auto token = person.dogs.observe([&](auto&& changes) { if (changes.collection_root_was_deleted) { std::cout << "The collection was deleted.\n"; } else { // Handle deletions, then insertions, then modifications. for (auto& collectionChange : changes.deletions) { std::cout << "The object at index " << std::to_string(collectionChange) << " was removed\n"; } for (auto& collectionChange : changes.insertions) { std::cout << "The object at index " << std::to_string(collectionChange) << " was inserted\n"; } for (auto& collectionChange : changes.modifications) { std::cout << "The object at index " << std::to_string(collectionChange) << " was modified\n"; } } }); // Remove an object from the collection, and then add an object to see // deletions and insertions. realm.write([&] { person.dogs.clear(); person.dogs.push_back(&dog2); }); // Modify an object to see a modification. realm.write([&] { dog2.age = 2; }); // Refresh the realm after the change to trigger the notification. realm.refresh(); // Unregister the token when done observing. token.unregister();
結果コレクション変更リスナーの登録
Realm は、書込みトランザクションによってコレクション内のオブジェクトが削除、追加、または変更されるたびにハンドラーに通知します。
通知は、削除、挿入、および変更されたオブジェクトのインデックスの 3 つのインデックス リストを使用して、前回の通知以降の変更を説明します。
重要
順序は重要
コレクション通知ハンドラーでは、削除、挿入、変更の順に常に変更を適用します。 削除前に挿入を処理すると、予期しない動作が発生する可能性があります。
結果コレクション通知では、削除、追加、または変更されたオブジェクトのインデックスを報告するResult_change構造体が提供されます。 コレクションが削除されたかどうかを通知することもできます。
// Get a results collection to observe auto dogs = realm.objects<realm::Dog>(); // Set up the listener & observe results notifications. auto token = dogs.observe([&](auto&& changes) { try { if (changes.collection_root_was_deleted) { std::cout << "The collection was deleted.\n"; } else { // Handle deletions, then insertions, then modifications. for (auto& resultsChange : changes.deletions) { std::cout << "The object at index " << std::to_string(resultsChange) << " was deleted\n"; } for (auto& resultsChange : changes.insertions) { std::cout << "The object at index " << std::to_string(resultsChange) << " was inserted\n"; } for (auto& resultsChange : changes.modifications) { std::cout << "The object at index " << std::to_string(resultsChange) << " was modified\n"; } } } catch (std::exception const& e) { std::cerr << "Error: " << e.what() << "\n"; } }); // Delete and then add an object to see deletions and insertions. realm.write([&] { realm.remove(firstDog); realm.add(std::move(dog2)); }); // Modify an object to see a modification. realm.write([&] { dog2.age = 2; }); // Refresh the database after the change to trigger the notification. realm.refresh(); // Unregister the token when done observing. token.unregister();
変更の監視を停止する
observe
呼び出しによって返されたトークンが無効になると、観察は停止します。 トークンを明示的に無効化するには、トークンのunregister()
ノード関数を呼び出します。
// Unregister the token when done observing. token.unregister();
重要
観察する必要がある限りトークンを保持する
トークンのデストラクターが呼び出されると通知が停止します。 たとえば、トークンがスコープ外のローカル変数にある場合。 std::move
を使用して、別のスコープの変数にトークンを転送できます。
通知制限の変更
4 レベルよりも深いネストされたドキュメントの変更では、変更通知はtriggerされません。
5 レベル以上の変更をリッスンする必要があるデータ構造がある場合は、次の回避策があります。
スキーマをリファクタリングしてネストを減らします。
ユーザーがデータを手動で更新できるようにするには、「push-to-refresh」のようなものを追加します。