在 Apple 平台上使用資料列表

獲取 FIR 數據庫參考

要從數據庫讀取或寫入數據,您需要一個FIRDatabaseReference實例:

迅速

注意:此 Firebase 產品在 App Clip 目標上不可用。
var ref: DatabaseReference!

ref = Database.database().reference()

Objective-C

注意:此 Firebase 產品在 App Clip 目標上不可用。
@property (strong, nonatomic) FIRDatabaseReference *ref;

self.ref = [[FIRDatabase database] reference];

閱讀和寫作列表

追加到數據列表

使用childByAutoId方法將數據追加到多用戶應用程序中的列表中。每次將新子項添加到指定的 Firebase 引用時, childByAutoId方法都會生成一個唯一鍵。通過為列表中的每個新元素使用這些自動生成的鍵,多個客戶端可以同時將子元素添加到同一位置,而不會發生寫入衝突。 childByAutoId生成的唯一鍵基於時間戳,因此列表項會自動按時間順序排序。

您可以使用對childByAutoId方法返回的新數據的引用來獲取子項自動生成的鍵的值或為子項設置數據。對childByAutoId引用調用getKey將返回自動生成的密鑰。

您可以使用這些自動生成的鍵來簡化數據結構的扁平化。有關更多信息,請參閱數據扇出示例

監聽子事件

子事件是為了響應節點子節點發生的特定操作而觸發的,這些操作例如通過childByAutoId方法添加的新子節點或通過updateChildValues方法更新的子節點。

事件類型典型用法
FIRDataEventTypeChildAdded檢索項目列表或偵聽項目列表的添加內容。對於每個現有子項,此事件都會觸發一次,然後每次將新子項添加到指定路徑時都會再次觸發。偵聽器會收到包含新子項數據的快照。
FIRDataEventTypeChildChanged監聽列表中項目的更改。每當修改子節點時都會觸發此事件。這包括對子節點的後代的任何修改。傳遞給事件偵聽器的快照包含子級的更新數據。
FIRDataEventTypeChildRemoved偵聽從列表中刪除的項目。當直接子項被刪除時,會觸發此事件。傳遞給回調塊的快照包含已刪除子項的數據。
FIRDataEventTypeChildMoved偵聽有序列表中項目順序的更改。每當更新導致子項重新排序時,就會觸發此事件。它與按queryOrderedByChildqueryOrderedByValue排序的數據一起使用。

這些中的每一個都可以用於偵聽數據庫中特定節點的更改。例如,社交博客應用程序可能會同時使用這些方法來監視帖子評論中的活動,如下所示:

迅速

注意:此 Firebase 產品在 App Clip 目標上不可用。
// 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

注意:此 Firebase 產品在 App Clip 目標上不可用。
// 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 返回,然後您可以循環訪問各個子項。

即使查詢只有一個匹配項,快照仍然是一個列表;它只包含一個項目。要訪問該項目,您需要循環結果:

迅速

注意:此 Firebase 產品在 App Clip 目標上不可用。
_commentsRef.observe(.value) { snapshot in
  for child in snapshot.children {
    ...
  }
}

Objective-C

注意:此 Firebase 產品在 App Clip 目標上不可用。
[_commentsRef
              observeEventType:FIRDataEventTypeValue
              withBlock:^(FIRDataSnapshot *snapshot) {
                // Loop over children
                NSEnumerator *children = [snapshot children];
                FIRDataSnapshot *child;
                while (child = [children nextObject]) {
                  // ...
                }
              }];

當您想要在單個操作中獲取列表的所有子項而不是偵聽其他子項添加事件時,此模式非常有用。

排序和過濾數據

您可以使用實時數據庫FIRDatabaseQuery類來檢索按鍵、按值或按子項值排序的數據。您還可以將排序結果過濾為特定數量的結果或一系列鍵或值。

對數據進行排序

要檢索排序的數據,請首先指定排序方法之一來確定結果的排序方式:

方法用法
queryOrderedByKey按子鍵對結果進行排序。
queryOrderedByValue按子值對結果進行排序。
queryOrderedByChild按指定子鍵或嵌套子路徑的值對結果進行排序。

您一次只能使用一種排序方式。在同一查詢中多次調用 order-by 方法會引發錯誤。

以下示例演示瞭如何檢索按星數排序的用戶熱門帖子列表:

迅速

注意:此 Firebase 產品在 App Clip 目標上不可用。
// My top posts by number of stars
let myTopPostsQuery = ref.child("user-posts").child(getUid()).queryOrdered(byChild: "starCount")

Objective-C

注意:此 Firebase 產品在 App Clip 目標上不可用。
// 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元素進行排序。

迅速

注意:此 Firebase 產品在 App Clip 目標上不可用。
 
let postsByMostPopular = ref.child("posts").queryOrdered(byChild: "metrics/views")

Objective-C

注意:此 Firebase 產品在 App Clip 目標上不可用。
 
FIRDatabaseQuery *postsByMostPopular = [[ref child:@"posts"] queryOrderedByChild:@"metrics/views"];

有關其他數據類型如何排序的詳細信息,請參閱查詢數據如何排序

過濾數據

要過濾數據,您可以在構造查詢時將任何限製或範圍方法與排序方法結合起來。

方法用法
queryLimitedToFirst設置從有序結果列表開頭返回的最大項目數。
queryLimitedToLast設置從有序結果列表末尾返回的最大項目數。
queryStartingAtValue返回大於或等於指定鍵或值的項目,具體取決於所選的排序方法。
queryStartingAfterValue返回大於指定鍵或值的項目,具體取決於所選的排序方法。
queryEndingAtValue返回小於或等於指定鍵或值的項目,具體取決於所選的排序方法。
queryEndingBeforeValue返回小於指定鍵或值的項目,具體取決於所選的排序方法。
queryEqualToValue返回等於指定鍵或值的項目,具體取決於所選的排序方法。

與排序方法不同,您可以組合多個限製或範圍函數。例如,您可以組合queryStartingAtValuequeryEndingAtValue方法將結果限制為指定的值範圍。

限制結果數量

您可以使用queryLimitedToFirstqueryLimitedToLast方法來設置給定回調要同步的最大子級數。例如,如果您使用queryLimitedToFirst將限制設置為 100,則最初最多只會收到 100 個FIRDataEventTypeChildAdded回調。如果 Firebase 數據庫中存儲的項目少於 100 個,則每個項目都會觸​​發FIRDataEventTypeChildAdded回調。

當項目發生更改時,您會收到輸入查詢的項目的FIRDataEventTypeChildAdded回調,以及退出查詢的項目的FIRDataEventTypeChildRemoved回調,以便總數保持在 100。

以下示例演示了示例博客應用程序如何檢索所有用戶最近發表的 100 篇帖子的列表:

迅速

注意:此 Firebase 產品在 App Clip 目標上不可用。
// 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

注意:此 Firebase 產品在 App Clip 目標上不可用。
// Last 100 posts, these are automatically the 100 most recent
// due to sorting by push() keys
FIRDatabaseQuery *recentPostsQuery = [[self.ref child:@"posts"] queryLimitedToFirst:100];

按鍵或值過濾

您可以使用queryStartingAtValuequeryStartingAfterValuequeryEndingAtValuequeryEndingBeforeValuequeryEqualToValue來選擇查詢的任意起始點、結束點和等價點。這對於對數據進行分頁或查找具有特定值的子項目非常有用。

查詢數據如何排序

本節介紹如何通過FIRDatabaseQuery類中的每個 order-by 方法對數據進行排序。

queryOrderedByKey

使用queryOrderedByKey對數據進行排序時,數據將按鍵升序返回。

  1. 具有可解析為 32 位整數的鍵的子項排在前面,按升序排序。
  2. 接下來是以字符串值作為鍵的子項,按字典順序升序排列。

queryOrderedByValue

使用queryOrderedByValue時,子級按其值排序。排序條件與queryOrderedByChild中的相同,只是使用節點的值而不是指定子鍵的值。

queryOrderedByChild

使用queryOrderedByChild時,包含指定子鍵的數據按如下方式排序:

  1. 指定子鍵的值為nil子項排在第一位。
  2. 接下來是指定子鍵值為false的子項。如果多個子項的值為false ,則它們按鍵按字典順序排序。
  3. 接下來是指定子鍵值為true的子項。如果多個子項的值為true ,則它們按鍵按字典順序排序。
  4. 接下來是具有數值的子項,按升序排序。如果指定子節點的多個子節點具有相同的數值,則它們按鍵排序。
  5. 字符串位於數字之後,並按字典順序升序排序。如果指定子節點的多個子節點具有相同的值,則它們按鍵按字典順序排序。
  6. 對象排在最後,並按字典順序按鍵升序排序。

分離監聽器

當您離開ViewController時,觀察者不會自動停止同步數據。如果觀察者沒有正確刪除,它會繼續將數據同步到本地內存,並保留在事件處理程序閉包中捕獲的任何對象,這可能會導致內存洩漏。當不再需要觀察者時,通過將關聯的FIRDatabaseHandle傳遞給removeObserverWithHandle方法來刪除它。

當您將回調塊添加到引用時,將返回FIRDatabaseHandle 。這些句柄可用於刪除回調塊。

如果已將多個偵聽器添加到數據庫引用,則引發事件時將調用每個偵聽器。為了停止在該位置同步數據,您必須通過調用removeAllObservers方法刪除該位置的所有觀察者。

在監聽器上調用removeObserverWithHandleremoveAllObservers不會自動刪除在其子節點上註冊的監聽器;您還必須跟踪這些引用或句柄以將其刪除。

下一步