FIRDatabaseReference を取得する
データベースからデータを読み書きするには、 FIRDatabaseReference
のインスタンスが必要です。
迅速
var ref: DatabaseReference! ref = Database.database().reference()
Objective-C
@property (strong, nonatomic) FIRDatabaseReference *ref; self.ref = [[FIRDatabase database] reference];
リストの読み書き
データのリストに追加
マルチユーザー アプリケーションのリストにデータを追加するには、 childByAutoId
メソッドを使用します。 childByAutoId
メソッドは、指定された Firebase 参照に新しい子が追加されるたびに一意のキーを生成します。リスト内の新しい要素ごとにこれらの自動生成されたキーを使用することにより、複数のクライアントが、書き込みの競合なしで同時に同じ場所に子を追加できます。 childByAutoId
によって生成される一意のキーはタイムスタンプに基づいているため、リスト アイテムは自動的に時系列順に並べられます。
childByAutoId
メソッドによって返された新しいデータへの参照を使用して、子の自動生成キーの値を取得したり、子のデータを設定したりできます。 childByAutoId
参照でgetKey
を呼び出すと、自動生成されたキーが返されます。
これらの自動生成されたキーを使用して、データ構造のフラット化を簡素化できます。詳細については、データ ファンアウトの例を参照してください。
子イベントをリッスンする
子イベントは、 childByAutoId
updateChildValues
によって更新された子などの操作からノードの子に発生する特定の操作に応答してトリガーされます。
イベントタイプ | 典型的な使用法 |
---|---|
FIRDataEventTypeChildAdded | アイテムのリストを取得するか、アイテムのリストへの追加をリッスンします。このイベントは、既存の子ごとに 1 回トリガーされ、指定されたパスに新しい子が追加されるたびに再度トリガーされます。リスナーには、新しい子のデータを含むスナップショットが渡されます。 |
FIRDataEventTypeChildChanged | リスト内の項目への変更をリッスンします。このイベントは、子ノードが変更されるたびにトリガーされます。これには、子ノードの子孫への変更が含まれます。イベント リスナーに渡されるスナップショットには、子の更新されたデータが含まれています。 |
FIRDataEventTypeChildRemoved | リストから削除される項目をリッスンします。このイベントは、直接の子が削除されたときにトリガーされます。コールバック ブロックに渡されるスナップショットには、削除された子のデータが含まれています。 |
FIRDataEventTypeChildMoved | 順序付きリスト内のアイテムの順序の変更をリッスンします。このイベントは、更新によって子の並べ替えが発生するたびにトリガーされます。 queryOrderedByChild またはqueryOrderedByValue によって並べ替えられたデータで使用されます。 |
これらはそれぞれ、データベース内の特定のノードへの変更をリッスンするのに役立ちます。たとえば、ソーシャル ブログ アプリでは、以下に示すように、これらのメソッドを一緒に使用して、投稿のコメント内のアクティビティを監視できます。
迅速
// Listen for new comments in the Firebase database commentsRef.observe(.childAdded, with: { (snapshot) -> Void in self.comments.append(snapshot) self.tableView.insertRows( at: [IndexPath(row: self.comments.count - 1, section: self.kSectionComments)], with: UITableView.RowAnimation.automatic ) }) // Listen for deleted comments in the Firebase database commentsRef.observe(.childRemoved, with: { (snapshot) -> Void in let index = self.indexOfMessage(snapshot) self.comments.remove(at: index) self.tableView.deleteRows( at: [IndexPath(row: index, section: self.kSectionComments)], with: UITableView.RowAnimation.automatic ) })
Objective-C
// Listen for new comments in the Firebase database [_commentsRef observeEventType:FIRDataEventTypeChildAdded withBlock:^(FIRDataSnapshot *snapshot) { [self.comments addObject:snapshot]; [self.tableView insertRowsAtIndexPaths:@[ [NSIndexPath indexPathForRow:self.comments.count - 1 inSection:kSectionComments] ] withRowAnimation:UITableViewRowAnimationAutomatic]; }]; // Listen for deleted comments in the Firebase database [_commentsRef observeEventType:FIRDataEventTypeChildRemoved withBlock:^(FIRDataSnapshot *snapshot) { int index = [self indexOfMessage:snapshot]; [self.comments removeObjectAtIndex:index]; [self.tableView deleteRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:index inSection:kSectionComments]] withRowAnimation:UITableViewRowAnimationAutomatic]; }];
値イベントをリッスンする
データのリストを読み取る方法として子イベントをリッスンすることをお勧めしますが、リスト参照の値イベントをリッスンすると便利な場合もあります。
FIRDataEventTypeValue
オブザーバーをデータのリストにアタッチすると、データのリスト全体が単一の DataSnapshot として返されます。これをループして個々の子にアクセスできます。
クエリに一致するものが 1 つしかない場合でも、スナップショットはリストのままです。単一のアイテムが含まれているだけです。アイテムにアクセスするには、結果をループする必要があります。
迅速
_commentsRef.observe(.value) { snapshot in for child in snapshot.children { ... } }
Objective-C
[_commentsRef observeEventType:FIRDataEventTypeValue withBlock:^(FIRDataSnapshot *snapshot) { // Loop over children NSEnumerator *children = [snapshot children]; FIRDataSnapshot *child; while (child = [children nextObject]) { // ... } }];
このパターンは、追加の子追加イベントをリッスンするのではなく、1 回の操作でリストのすべての子をフェッチする場合に役立ちます。
データのソートとフィルタリング
Realtime Database FIRDatabaseQuery
クラスを使用して、キー、値、または子の値で並べ替えられたデータを取得できます。並べ替えられた結果を特定の数の結果またはキーまたは値の範囲にフィルター処理することもできます。
データの並べ替え
並べ替えられたデータを取得するには、次のいずれかの order-by メソッドを指定して、結果の並べ替え方法を決定することから始めます。
方法 | 使用法 |
---|---|
queryOrderedByKey | 結果を子キーで並べ替えます。 |
queryOrderedByValue | 結果を子の値で並べ替えます。 |
queryOrderedByChild | 指定された子キーまたはネストされた子パスの値で結果を並べ替えます。 |
一度に使用できる order-by メソッドは1 つだけです。同じクエリで order-by メソッドを複数回呼び出すと、エラーがスローされます。
次の例は、星の数で並べ替えられたユーザーのトップ投稿のリストを取得する方法を示しています。
迅速
// My top posts by number of stars let myTopPostsQuery = ref.child("user-posts").child(getUid()).queryOrdered(byChild: "starCount")
Objective-C
// My top posts by number of stars FIRDatabaseQuery *myTopPostsQuery = [[[self.ref child:@"user-posts"] child:[super getUid]] queryOrderedByChild:@"starCount"];
このクエリは、ユーザー ID に基づいてデータベース内のパスからユーザーの投稿を取得し、各投稿が受け取った星の数で並べ替えます。 ID をインデックス キーとして使用するこの手法は、データ ファン アウトと呼ばれます。詳細については、データベースの構築 を参照してください。
queryOrderedByChild
メソッドの呼び出しは、結果の順序付けに使用する子キーを指定します。この例では、投稿は各投稿の"starCount"
子の値によって並べ替えられます。次のようなデータがある場合は、ネストされた子によってクエリを並べ替えることもできます。
"posts": { "ts-functions": { "metrics": { "views" : 1200000, "likes" : 251000, "shares": 1200, }, "title" : "Why you should use TypeScript for writing Cloud Functions", "author": "Doug", }, "android-arch-3": { "metrics": { "views" : 900000, "likes" : 117000, "shares": 144, }, "title" : "Using Android Architecture Components with Firebase Realtime Database (Part 3)", "author": "Doug", } },
この場合、 queryOrderedByChild
呼び出しでネストされた子への相対パスを指定することで、 metrics
キーの下にネストされた値でリスト要素を並べ替えることができます。
迅速
let postsByMostPopular = ref.child("posts").queryOrdered(byChild: "metrics/views")
Objective-C
FIRDatabaseQuery *postsByMostPopular = [[ref child:@"posts"] queryOrderedByChild:@"metrics/views"];
他のデータ型の順序付けの詳細については、クエリ データの順序付け方法を参照してください。
データのフィルタリング
データをフィルター処理するには、クエリを作成するときに limit メソッドまたは range メソッドを order-by メソッドと組み合わせることができます。
方法 | 使用法 |
---|---|
queryLimitedToFirst | 結果の順序付きリストの先頭から返す項目の最大数を設定します。 |
queryLimitedToLast | 結果の順序付けられたリストの最後から返される項目の最大数を設定します。 |
queryStartingAtValue | 選択した order-by メソッドに応じて、指定されたキーまたは値以上のアイテムを返します。 |
queryStartingAfterValue | 選択した order-by メソッドに応じて、指定されたキーまたは値より大きいアイテムを返します。 |
queryEndingAtValue | 選択した order-by メソッドに応じて、指定されたキーまたは値以下のアイテムを返します。 |
queryEndingBeforeValue | 選択された order-by メソッドに応じて、指定されたキーまたは値より少ないアイテムを返します。 |
queryEqualToValue | 選択した order-by メソッドに応じて、指定されたキーまたは値に等しい項目を返します。 |
order-by メソッドとは異なり、複数の limit または range 関数を組み合わせることができます。たとえば、 queryStartingAtValue
メソッドとqueryEndingAtValue
メソッドを組み合わせて、結果を指定された範囲の値に制限できます。
結果の数を制限する
queryLimitedToLast
queryLimitedToFirst
を使用して、特定のコールバックで同期する子の最大数を設定できます。たとえば、 queryLimitedToFirst
を使用して制限を 100 に設定した場合、最初は最大 100 のFIRDataEventTypeChildAdded
コールバックしか受け取りません。 Firebase データベースに保存されているアイテムが 100 未満の場合、アイテムごとにFIRDataEventTypeChildAdded
コールバックが発生します。
項目が変更されると、クエリに入る項目に対してFIRDataEventTypeChildAdded
コールバックを受け取り、クエリから脱落する項目に対してFIRDataEventTypeChildRemoved
コールバックを受け取り、合計数が 100 のままになるようにします。
次の例は、サンプル ブログ アプリがすべてのユーザーによる最新の 100 件の投稿のリストを取得する方法を示しています。
迅速
// Last 100 posts, these are automatically the 100 most recent // due to sorting by push() keys let recentPostsQuery = (ref?.child("posts").queryLimited(toFirst: 100))!
Objective-C
// Last 100 posts, these are automatically the 100 most recent // due to sorting by push() keys FIRDatabaseQuery *recentPostsQuery = [[self.ref child:@"posts"] queryLimitedToFirst:100];
キーまたは値でフィルタ
queryStartingAtValue
、 queryStartingAfterValue
、 queryEndingAtValue
、 queryEndingBeforeValue
、およびqueryEqualToValue
を使用して、クエリの任意の開始点、終了点、および等価点を選択できます。これは、データのページ付けや、特定の値を持つ子を持つアイテムの検索に役立ちます。
クエリ データの順序付け方法
このセクションでは、 FIRDatabaseQuery
クラスの各 order-by メソッドによってデータがどのように並べ替えられるかについて説明します。
queryOrderedByKey
queryOrderedByKey
を使用してデータを並べ替えると、データはキーの昇順で返されます。
- 32 ビット整数として解析できるキーを持つ子が最初に来て、昇順でソートされます。
- 次にキーとして文字列値を持つ子が来て、辞書式に昇順にソートされます。
queryOrderedByValue
queryOrderedByValue
を使用すると、子はその値によって並べ替えられます。指定された子キーの値の代わりにノードの値が使用されることを除いて、順序付け基準はqueryOrderedByChild
と同じです。
queryOrderedByChild
queryOrderedByChild
を使用する場合、指定された子キーを含むデータは次のように並べられます。
- 指定された子キーの値が
nil
の子が最初に来ます。 - 指定された子キーの値が
false
の子が次に来ます。複数の子の値がfalse
の場合、それらはキーによって辞書順にソートされます。 - 指定された子キーの値が
true
の子が次に来ます。複数の子の値がtrue
の場合、それらは辞書式にキーでソートされます。 - 次に、数値を持つ子が昇順でソートされます。複数の子が指定された子ノードに対して同じ数値を持つ場合、それらはキーでソートされます。
- 文字列は数値の後に続き、辞書式に昇順にソートされます。指定された子ノードに対して複数の子が同じ値を持つ場合、それらはキーによって辞書順に並べられます。
- オブジェクトは最後に来て、キーの昇順で辞書式にソートされます。
リスナーを切り離す
ViewController
を離れても、オブザーバーはデータの同期を自動的に停止しません。オブザーバーが適切に削除されない場合、オブザーバーは引き続きデータをローカル メモリに同期し、イベント ハンドラー クロージャーでキャプチャされたオブジェクトを保持します。これにより、メモリ リークが発生する可能性があります。オブザーバーが不要になったら、関連するFIRDatabaseHandle
をremoveObserverWithHandle
メソッドに渡して削除します。
コールバック ブロックを参照に追加すると、 FIRDatabaseHandle
が返されます。これらのハンドルを使用して、コールバック ブロックを削除できます。
複数のリスナーがデータベース参照に追加されている場合、イベントが発生すると各リスナーが呼び出されます。その場所でデータの同期を停止するには、 removeAllObservers
メソッドを呼び出して、その場所にあるすべてのオブザーバーを削除する必要があります。
リスナーでremoveObserverWithHandle
またはremoveAllObservers
を呼び出しても、その子ノードに登録されているリスナーは自動的に削除されません。それらを削除するには、それらの参照またはハンドルを追跡する必要もあります。