Arbeiten mit Datenlisten unter iOS

Holen Sie sich eine FIRDatenbank-Referenz

Um Daten aus der Datenbank zu lesen oder zu schreiben, benötigen Sie eine Instanz von FIRDatabaseReference :

Schnell

var ref: DatabaseReference!

ref = Database.database().reference()

Ziel c

@property (strong, nonatomic) FIRDatabaseReference *ref;

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

Listen lesen und schreiben

An eine Datenliste anhängen

Verwenden Sie die Methode childByAutoId , um in Mehrbenutzeranwendungen Daten an eine Liste anzuhängen. Die Methode childByAutoId generiert jedes Mal einen eindeutigen Schlüssel, wenn der angegebenen Firebase-Referenz ein neues Kind hinzugefügt wird. Durch die Verwendung dieser automatisch generierten Schlüssel für jedes neue Element in der Liste können mehrere Clients gleichzeitig untergeordnete Elemente ohne Schreibkonflikte am selben Speicherort hinzufügen. Der von childByAutoId generierte eindeutige Schlüssel basiert auf einem Zeitstempel, sodass Listenelemente automatisch chronologisch sortiert werden.

Sie können den Verweis auf die neuen Daten verwenden, die von der childByAutoId Methode zurückgegeben werden, um den Wert des automatisch generierten Schlüssels des childByAutoId oder Daten für das childByAutoId . Der Aufruf von getKey für eine childByAutoId Referenz gibt den automatisch generierten Schlüssel zurück.

Sie können diese automatisch generierten Schlüssel verwenden, um die Reduzierung Ihrer Datenstruktur zu vereinfachen. Weitere Informationen finden Sie im Beispiel zum Auffächern von Daten .

Auf Kinderereignisse achten

Kinderveranstaltungen werden in Reaktion auf bestimmte Vorgänge ausgelöst, die von einer Operation an die Kinder eines Knotens geschehen wie ein neues Kind aufgenommen durch die childByAutoId Verfahren oder ein Kind durch die aktualisiert werden updateChildValues Methode.

Ereignistyp Typische Verwendung
FIRDataEventTypeChildAdded Rufen Sie Listen von Elementen ab oder hören Sie auf Ergänzungen zu einer Liste von Elementen. Dieses Ereignis wird einmal für jedes vorhandene Kind ausgelöst und dann jedes Mal, wenn dem angegebenen Pfad ein neues Kind hinzugefügt wird. Dem Listener wird ein Snapshot übergeben, der die Daten des neuen untergeordneten Elements enthält.
FIRDataEventTypeChildChanged Achten Sie auf Änderungen an den Elementen in einer Liste. Dieses Ereignis wird jedes Mal ausgelöst, wenn ein untergeordneter Knoten geändert wird. Dies schließt alle Änderungen an Nachkommen des untergeordneten Knotens ein. Der an den Ereignis-Listener übergebene Snapshot enthält die aktualisierten Daten für das untergeordnete Element.
FIRDataEventTypeChildRemoved Achten Sie darauf, dass Elemente aus einer Liste entfernt werden. Dieses Ereignis wird ausgelöst, wenn ein unmittelbar untergeordnetes Element entfernt wird. Der an den Rückrufblock übergebene Snapshot enthält die Daten für das entfernte untergeordnete Element.
FIRDataEventTypeChildMoved Achten Sie auf Änderungen an der Reihenfolge der Elemente in einer geordneten Liste. Dieses Ereignis wird immer dann ausgelöst, wenn eine Aktualisierung eine Neuordnung des untergeordneten Elements verursacht. Es wird mit Daten verwendet, die nach queryOrderedByChild oder queryOrderedByValue .

Alle zusammen können nützlich sein, um Änderungen an einem bestimmten Knoten in einer Datenbank abzuhören. Beispielsweise kann eine Social-Blogging-App diese Methoden zusammen verwenden, um die Aktivität in den Kommentaren eines Beitrags zu überwachen, wie unten gezeigt:

Schnell

// 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)
})

Ziel 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];
 }];

Auf Wertereignisse achten

Während das Abhören von untergeordneten Ereignissen die empfohlene Methode zum Lesen von Datenlisten ist, gibt es Situationen, in denen das Abhören von Wertereignissen in einer Listenreferenz nützlich ist.

FIRDataEventTypeValue einen FIRDataEventTypeValue Beobachter an eine FIRDataEventTypeValue , wird die gesamte FIRDataEventTypeValue als einzelner DataSnapshot zurückgegeben, den Sie dann durchschleifen können, um auf einzelne Kinder zuzugreifen.

Auch wenn es nur eine einzige Übereinstimmung für die Abfrage gibt, ist der Snapshot immer noch eine Liste; es enthält nur ein einzelnes Element. Um auf das Element zuzugreifen, müssen Sie das Ergebnis durchlaufen:

Schnell

_commentsRef.observe(.value) { snapshot in
  for child in snapshot.children {
    ...
  }
}

Ziel c

[_commentsRef
              observeEventType:FIRDataEventTypeValue
              withBlock:^(FIRDataSnapshot *snapshot) {
                // Loop over children
                NSEnumerator *children = [snapshot children];
                FIRDataSnapshot *child;
                while (child = [children nextObject]) {
                  // ...
                }
              }];

Dieses Muster kann nützlich sein, wenn Sie alle untergeordneten Elemente einer Liste in einem einzigen Vorgang abrufen möchten, anstatt auf zusätzliche untergeordnete Ereignisse zu warten.

Daten sortieren und filtern

Sie können die FIRDatabaseQuery Klasse der Realtime Database FIRDatabaseQuery , um Daten abzurufen, die nach Schlüssel, Wert oder Wert eines FIRDatabaseQuery sortiert sind. Sie können das sortierte Ergebnis auch nach einer bestimmten Anzahl von Ergebnissen oder einem Bereich von Schlüsseln oder Werten filtern.

Daten sortieren

Um sortierte Daten abzurufen, geben Sie zunächst eine der Sortiermethoden an, um zu bestimmen, wie die Ergebnisse sortiert werden:

Methode Verwendung
queryOrderedByKey Sortieren Sie die Ergebnisse nach untergeordneten Schlüsseln.
queryOrderedByValue Sortieren Sie die Ergebnisse nach untergeordneten Werten.
queryOrderedByChild Sortieren Sie die Ergebnisse nach dem Wert eines angegebenen untergeordneten Schlüssels oder verschachtelten untergeordneten Pfads.

Sie können jeweils nur eine Bestellmethode verwenden. Das mehrmalige Aufrufen einer order-by-Methode in derselben Abfrage führt zu einem Fehler.

Das folgende Beispiel zeigt, wie Sie eine Liste der Top-Posts eines Benutzers, sortiert nach ihrer Sternzahl, abrufen können:

Schnell

// My top posts by number of stars
let myTopPostsQuery = (ref.child("user-posts").child(getUid())).queryOrdered(byChild: "starCount")

Ziel c

// My top posts by number of stars
FIRDatabaseQuery *myTopPostsQuery = [[[self.ref child:@"user-posts"]
                                      child:[super getUid]]
                                     queryOrderedByChild:@"starCount"];

Diese Abfrage ruft die Beiträge des Benutzers aus dem Pfad in der Datenbank basierend auf seiner Benutzer-ID ab, geordnet nach der Anzahl der Sterne, die jeder Beitrag erhalten hat. Diese Technik der Verwendung von IDs als Indexschlüssel wird als Datenauffächerung bezeichnet. Sie können mehr darüber in Strukturieren Ihrer Datenbank lesen.

Der Aufruf der Methode queryOrderedByChild gibt den queryOrderedByChild Schlüssel an, nach dem die Ergebnisse sortiert werden sollen. In diesem Beispiel werden die Beiträge nach dem Wert des "starCount" in jedem Beitrag sortiert. Abfragen können auch nach verschachtelten Kindern geordnet werden, falls Sie Daten haben, die wie folgt aussehen:

"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",
  }
},

In diesem Fall können wir unsere Listenelemente durch Werte verschachtelt unter der Bestellnummer metrics Schlüssel durch den relativen Pfad zu dem verschachtelten Kind in unserer Angabe queryOrderedByChild Anruf.

Schnell

 
let postsByMostPopular = ref.child("posts").queryOrdered(byChild: "metrics/views")

Ziel c

 
FIRDatabaseQuery *postsByMostPopular = [[ref child:@"posts"] queryOrderedByChild:@"metrics/views"];

Weitere Informationen zum Sortieren anderer Datentypen finden Sie unter Sortieren von Abfragedaten .

Daten filtern

Um Daten zu filtern, können Sie beim Erstellen einer Abfrage jede der Limit- oder Range-Methoden mit einer order-by-Methode kombinieren.

Methode Verwendung
queryLimitedToFirst Legt die maximale Anzahl von Elementen fest, die vom Anfang der geordneten Ergebnisliste zurückgegeben werden sollen.
queryLimitedToLast Legt die maximale Anzahl von Elementen fest, die vom Ende der geordneten Ergebnisliste zurückgegeben werden sollen.
queryStartingAtValue Gibt Elemente zurück, die größer oder gleich dem angegebenen Schlüssel oder Wert sind, abhängig von der ausgewählten Sortiermethode.
queryStartingAfterValue Gibt Elemente zurück, die größer als der angegebene Schlüssel oder Wert sind, abhängig von der ausgewählten Sortiermethode.
queryEndingAtValue Geben Sie Elemente zurück, die kleiner oder gleich dem angegebenen Schlüssel oder Wert sind, abhängig von der ausgewählten Sortiermethode.
queryEndingBeforeValue Geben Sie Elemente zurück, die weniger als den angegebenen Schlüssel oder Wert aufweisen, je nach gewählter Sortiermethode.
queryEqualToValue Geben Sie Elemente zurück, die dem angegebenen Schlüssel oder Wert entsprechen, abhängig von der ausgewählten Sortiermethode.

Im Gegensatz zu den Sortiermethoden können Sie mehrere Grenzwert- oder Bereichsfunktionen kombinieren. Sie können beispielsweise die Methoden queryStartingAtValue und queryEndingAtValue kombinieren, um die Ergebnisse auf einen angegebenen Wertebereich zu beschränken.

Begrenzen Sie die Anzahl der Ergebnisse

Sie können die Methoden queryLimitedToFirst und queryLimitedToLast verwenden, um eine maximale Anzahl von queryLimitedToLast queryLimitedToFirst queryLimitedToLast , die für einen bestimmten Rückruf synchronisiert werden sollen. Wenn Sie beispielsweise queryLimitedToFirst , um ein Limit von 100 queryLimitedToFirst , erhalten Sie zunächst nur bis zu 100 FIRDataEventTypeChildAdded Callbacks. Wenn in Ihrer Firebase-Datenbank weniger als 100 Elemente gespeichert sind, wird für jedes Element ein FIRDataEventTypeChildAdded Rückruf FIRDataEventTypeChildAdded .

Wenn sich Elemente ändern, erhalten Sie FIRDataEventTypeChildAdded Rückrufe für Elemente, die in die Abfrage eingehen, und FIRDataEventTypeChildRemoved Rückrufe für Elemente, die aus ihr herausfallen, sodass die Gesamtzahl bei 100 bleibt.

Das folgende Beispiel zeigt, wie eine Beispiel-Blogging-App eine Liste der 100 neuesten Beiträge aller Benutzer abrufen könnte:

Schnell

// Last 100 posts, these are automatically the 100 most recent
// due to sorting by push() keys
let recentPostsQuery = (ref?.child("posts").queryLimited(toFirst: 100))!

Ziel 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];

Nach Schlüssel oder Wert filtern

Sie können queryStartingAtValue , queryStartingAfterValue , queryEndingAtValue , queryEndingBeforeValue und queryEqualToValue , um beliebige Start-, End- und Äquivalenzpunkte für Abfragen auszuwählen. Dies kann nützlich sein, um Daten zu paginieren oder Elemente mit untergeordneten Elementen zu finden, die einen bestimmten Wert haben.

So werden Abfragedaten geordnet

In diesem Abschnitt wird erläutert, wie Daten nach jeder der order-by-Methoden in der FIRDatabaseQuery Klasse sortiert werden.

queryOrderedByKey

Wenn Sie queryOrderedByKey zum Sortieren Ihrer Daten verwenden, werden die Daten in aufsteigender Reihenfolge nach Schlüssel zurückgegeben.

  1. Kinder mit einem Schlüssel, der als 32-Bit-Ganzzahl geparst werden kann, kommen zuerst, sortiert in aufsteigender Reihenfolge.
  2. Als nächstes kommen Kinder mit einem String-Wert als Schlüssel, lexikographisch aufsteigend sortiert.

queryOrderedByValue

Bei Verwendung von queryOrderedByValue werden queryOrderedByValue nach ihrem Wert sortiert. Die queryOrderedByChild sind dieselben wie in queryOrderedByChild , außer dass der Wert des Knotens anstelle des Werts eines angegebenen queryOrderedByChild Schlüssels verwendet wird.

queryOrderedByChild

Bei Verwendung von queryOrderedByChild werden Daten, die den angegebenen queryOrderedByChild Schlüssel enthalten, wie folgt sortiert:

  1. Kinder mit einem nil für den angegebenen untergeordneten Schlüssel kommen zuerst.
  2. Als nächstes kommen untergeordnete Elemente mit dem Wert false für den angegebenen untergeordneten Schlüssel. Wenn mehrere Kinder den Wert false , werden sie lexikografisch nach Schlüssel sortiert.
  3. Als nächstes kommen untergeordnete Elemente mit dem Wert true für den angegebenen untergeordneten Schlüssel. Wenn mehrere Kinder den Wert true , werden sie lexikografisch nach Schlüssel sortiert.
  4. Als nächstes folgen Kinder mit einem numerischen Wert, sortiert in aufsteigender Reihenfolge. Wenn mehrere untergeordnete Knoten denselben numerischen Wert für den angegebenen untergeordneten Knoten haben, werden sie nach dem Schlüssel sortiert.
  5. Strings kommen nach Zahlen und werden lexikographisch aufsteigend sortiert. Wenn mehrere Kinder denselben Wert für den angegebenen Kindknoten haben, werden sie lexikografisch nach Schlüssel sortiert.
  6. Objekte stehen an letzter Stelle und werden lexikographisch nach Schlüsseln in aufsteigender Reihenfolge sortiert.

Hörer trennen

Beobachter beenden die Synchronisierung von Daten nicht automatisch, wenn Sie einen ViewController verlassen. Wenn ein Beobachter nicht ordnungsgemäß entfernt wird, synchronisiert er weiterhin Daten mit dem lokalen Speicher und behält alle beim Schließen des Ereignishandlers erfassten Objekte bei, was zu Speicherverlusten führen kann. Wenn ein Beobachter nicht mehr benötigt wird, entfernen Sie ihn, indem Sie das zugehörige FIRDatabaseHandle an die Methode removeObserverWithHandle .

Wenn Sie einer Referenz einen Callback-Block hinzufügen, wird ein FIRDatabaseHandle zurückgegeben. Diese Handles können verwendet werden, um den Callback-Block zu entfernen.

Wenn einer Datenbankreferenz mehrere Listener hinzugefügt wurden, wird jeder Listener aufgerufen, wenn ein Ereignis ausgelöst wird. Um die Synchronisierung von Daten an diesem Speicherort zu beenden, müssen Sie alle Beobachter an einem Speicherort entfernen, indem Sie die Methode removeAllObservers aufrufen.

Das Aufrufen von removeObserverWithHandle oder removeAllObservers auf einem Listener entfernt nicht automatisch Listener, die auf seinen removeAllObservers Knoten registriert sind. Sie müssen auch diese Referenzen oder Handles verfolgen, um sie zu entfernen.

Nächste Schritte