在 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不會自動刪除在其子節點上註冊的監聽器;您還必須追蹤這些引用或句柄以將其刪除。

下一步