使用 Apple 平台上的資料清單

取得 FIRDatabaseReference

如要從資料庫讀取或寫入資料,您需要 FIRDatabaseReference 的執行個體:

SwiftObjective-C

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

ref = Database.database().reference()

注意:這個 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 監聽有序清單中項目的順序變更。 每當更新導致子項重新排序時,就會觸發這個事件。這項功能適用於依 queryOrderedByChild queryOrderedByValue 排序的資料。

這些方法結合起來,可用於監聽資料庫中特定節點的變更。舉例來說,社群部落格應用程式可能會一併使用這些方法,監控貼文留言中的活動,如下所示:

SwiftObjective-C

注意:這個 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
  )
})

注意:這個 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 傳回,您隨後可以逐一存取個別子項。

即使查詢只找到一個相符項目,快照仍會是清單,只是只包含一個項目。如要存取項目,您需要對結果進行迴圈:

SwiftObjective-C

注意:這個 Firebase 產品不適用於 App Clip 目標。
_commentsRef.observe(.value) { snapshot in
  for child in snapshot.children {
    ...
  }
}

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

如果您想在單一作業中擷取清單的所有子項,而非監聽額外子項新增事件,這個模式就非常實用。

排序及篩選資料

您可以使用 Realtime Database FIRDatabaseQuery 類別,依鍵、值或子項的值擷取排序後的資料。您也可以將排序結果篩選為特定結果數,或是特定範圍的鍵或值。

排序資料

如要擷取排序後的資料,請先指定其中一個排序依據方法,決定結果的排序方式:

方法 用量
queryOrderedByKey 依子項鍵排序結果。
queryOrderedByValue 依子項值排序結果。
queryOrderedByChild 依據指定子項鍵或巢狀子項路徑的值排序結果。

一次只能使用一種排序依據方法。在同一項查詢中多次呼叫 order-by 方法會擲回錯誤。

以下範例說明如何擷取使用者熱門貼文的清單,並依星等排序:

SwiftObjective-C

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

注意:這個 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 鍵下巢狀結構的值排序清單元素。

SwiftObjective-C

注意:這個 Firebase 產品不適用於 App Clip 目標。
 
let postsByMostPopular = ref.child("posts").queryOrdered(byChild: "metrics/views")

注意:這個 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 則貼文的清單:

SwiftObjective-C

注意:這個 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))!

注意:這個 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. 接著是數值,並以遞增順序排序。如果多個子項的指定子項節點具有相同的數值,系統會依鍵排序。
  5. 字串會排在數字後面,並依字典順序遞增排序。如果多個子項在指定的子項節點中具有相同的值,系統會依鍵的字典順序排序。
  6. 物件會排在最後,並依鍵以遞增順序按字母排序。

卸離監聽器

離開 ViewController 後,觀察員不會自動停止同步資料。如果觀察器未正確移除,系統會繼續將資料同步至本機記憶體,並保留事件處理常式封閉中擷取的任何物件,這可能會導致記憶體洩漏。不再需要觀察器時,請將相關聯的 FIRDatabaseHandle 傳遞至 removeObserverWithHandle 方法,即可移除觀察器。

將回呼區塊新增至參照時,系統會傳回 FIRDatabaseHandle。這些控制代碼可用來移除回呼區塊。

如果已將多個監聽器新增至資料庫參照,系統會在引發事件時呼叫每個監聽器。如要停止同步處理該位置的資料,您必須呼叫 removeAllObservers 方法,移除該位置的所有觀察者。

在監聽器上呼叫 removeObserverWithHandleremoveAllObservers 不會自動移除在子節點上註冊的監聽器,您也必須追蹤這些參照或控制代碼,才能移除監聽器。

後續步驟