在 Apple 平台上使用數據列表

獲取 FIRDatabaseReference

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

迅速

注意:此 Firebase 產品不適用於 App Clip 目標。
var ref: DatabaseReference!

ref = Database.database().reference()

目標-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
  )
})

目標-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 {
    ...
  }
}

目標-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")

目標-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")

目標-C

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

有關其他數據類型如何排序的更多信息,請參閱查詢數據的排序方式

過濾數據

要過濾數據,您可以在構造查詢時將任何 limit 或 range 方法與 order-by 方法結合使用。

方法用法
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))!

目標-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類中的每個排序方法對數據進行排序。

queryOrderedByKey

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

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

queryOrderedByValue

使用queryOrderedByValue時,子項按其值排序。排序標準與queryOrderedByChild中的相同,除了使用節點的值而不是指定子鍵的值。

queryOrderedByChild

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

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

分離監聽器

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

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

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

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

下一步