Trabajar con listas de datos en plataformas Apple

Obtener una referencia de base de datos FIR

Para leer o escribir datos de la base de datos, necesita una instancia de FIRDatabaseReference :

Rápido

Nota: Este producto de Firebase no está disponible en el destino del clip de aplicación.
var ref: DatabaseReference!

ref = Database.database().reference()

C objetivo

Nota: Este producto de Firebase no está disponible en el destino del clip de aplicación.
@property (strong, nonatomic) FIRDatabaseReference *ref;

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

Listas de lectura y escritura.

Agregar a una lista de datos

Utilice el método childByAutoId para agregar datos a una lista en aplicaciones multiusuario. El método childByAutoId genera una clave única cada vez que se agrega un nuevo elemento secundario a la referencia de Firebase especificada. Al utilizar estas claves generadas automáticamente para cada elemento nuevo de la lista, varios clientes pueden agregar elementos secundarios a la misma ubicación al mismo tiempo sin conflictos de escritura. La clave única generada por childByAutoId se basa en una marca de tiempo, por lo que los elementos de la lista se ordenan automáticamente cronológicamente.

Puede utilizar la referencia a los nuevos datos devueltos por el método childByAutoId para obtener el valor de la clave generada automáticamente del niño o establecer datos para el niño. Llamar getKey en una referencia childByAutoId devuelve la clave generada automáticamente.

Puede utilizar estas claves generadas automáticamente para simplificar el aplanamiento de su estructura de datos. Para obtener más información, consulte el ejemplo de distribución de datos.

Escuche eventos infantiles

Los eventos secundarios se activan en respuesta a operaciones específicas que les suceden a los elementos secundarios de un nodo a partir de una operación, como un nuevo elemento secundario agregado mediante el método childByAutoId o un elemento secundario que se actualiza mediante el método updateChildValues .

Tipo de evento Uso típico
FIRDataEventTypeChildAdded Recupera listas de elementos o escucha adiciones a una lista de elementos. Este evento se activa una vez para cada hijo existente y luego nuevamente cada vez que se agrega un hijo nuevo a la ruta especificada. Al oyente se le pasa una instantánea que contiene los datos del nuevo niño.
FIRDataEventTypeChildChanged Escuche los cambios en los elementos de una lista. Este evento se activa cada vez que se modifica un nodo secundario. Esto incluye cualquier modificación a los descendientes del nodo hijo. La instantánea pasada al detector de eventos contiene los datos actualizados del niño.
FIRDataEventTypeChildRemoved Escuche los elementos que se eliminan de una lista. Este evento se activa cuando se elimina un hijo inmediato. La instantánea pasada al bloque de devolución de llamada contiene los datos del hijo eliminado.
FIRDataEventTypeChildMoved Escuche los cambios en el orden de los elementos en una lista ordenada. Este evento se activa cada vez que una actualización provoca un reordenamiento del niño. Se utiliza con datos ordenados por queryOrderedByChild o queryOrderedByValue .

Cada uno de estos juntos puede ser útil para escuchar cambios en un nodo específico en una base de datos. Por ejemplo, una aplicación de blogs sociales podría utilizar estos métodos juntos para monitorear la actividad en los comentarios de una publicación, como se muestra a continuación:

Rápido

Nota: Este producto de Firebase no está disponible en el destino del clip de aplicación.
// 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 objetivo

Nota: Este producto de Firebase no está disponible en el destino del clip de aplicación.
// 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];
 }];

Escuche eventos de valor

Si bien escuchar eventos secundarios es la forma recomendada de leer listas de datos, hay situaciones en las que es útil escuchar eventos de valor en una referencia de lista.

Adjuntar un observador FIRDataEventTypeValue a una lista de datos devolverá la lista completa de datos como una única instantánea de datos, que luego puede recorrer para acceder a niños individuales.

Incluso cuando solo hay una coincidencia para la consulta, la instantánea sigue siendo una lista; solo contiene un solo elemento. Para acceder al elemento, debe recorrer el resultado:

Rápido

Nota: Este producto de Firebase no está disponible en el destino del clip de aplicación.
_commentsRef.observe(.value) { snapshot in
  for child in snapshot.children {
    ...
  }
}

C objetivo

Nota: Este producto de Firebase no está disponible en el destino del clip de aplicación.
[_commentsRef
              observeEventType:FIRDataEventTypeValue
              withBlock:^(FIRDataSnapshot *snapshot) {
                // Loop over children
                NSEnumerator *children = [snapshot children];
                FIRDataSnapshot *child;
                while (child = [children nextObject]) {
                  // ...
                }
              }];

Este patrón puede resultar útil cuando desea recuperar todos los elementos secundarios de una lista en una sola operación, en lugar de escuchar eventos secundarios adicionales agregados.

Ordenar y filtrar datos

Puede utilizar la clase FIRDatabaseQuery de Realtime Database para recuperar datos ordenados por clave, por valor o por el valor de un hijo. También puede filtrar el resultado ordenado según un número específico de resultados o un rango de claves o valores.

ordenar datos

Para recuperar datos ordenados, comience especificando uno de los métodos de ordenación para determinar cómo se ordenan los resultados:

Método Uso
queryOrderedByKey Ordene los resultados por claves secundarias.
queryOrderedByValue Ordene los resultados por valores secundarios.
queryOrderedByChild Ordene los resultados por el valor de una clave secundaria especificada o una ruta secundaria anidada.

Sólo puedes utilizar un método de orden por vez. Llamar a un método de orden por varias veces en la misma consulta genera un error.

El siguiente ejemplo demuestra cómo puedes recuperar una lista de las publicaciones principales de un usuario ordenadas por su número de estrellas:

Rápido

Nota: Este producto de Firebase no está disponible en el destino del clip de aplicación.
// My top posts by number of stars
let myTopPostsQuery = ref.child("user-posts").child(getUid()).queryOrdered(byChild: "starCount")

C objetivo

Nota: Este producto de Firebase no está disponible en el destino del clip de aplicación.
// My top posts by number of stars
FIRDatabaseQuery *myTopPostsQuery = [[[self.ref child:@"user-posts"]
                                      child:[super getUid]]
                                     queryOrderedByChild:@"starCount"];

Esta consulta recupera las publicaciones del usuario de la ruta en la base de datos según su ID de usuario, ordenadas por la cantidad de estrellas que ha recibido cada publicación. Esta técnica de utilizar ID como claves de índice se denomina distribución en abanico de datos; puede leer más sobre esto en Estructurar su base de datos .

La llamada al método queryOrderedByChild especifica la clave secundaria para ordenar los resultados. En este ejemplo, las publicaciones se ordenan por el valor del elemento secundario "starCount" en cada publicación. Las consultas también se pueden ordenar por elementos secundarios anidados, en caso de que tenga datos similares a estos:

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

En este caso, podemos ordenar los elementos de nuestra lista por valores anidados bajo la clave metrics especificando la ruta relativa al hijo anidado en nuestra llamada queryOrderedByChild .

Rápido

Nota: Este producto de Firebase no está disponible en el destino del clip de aplicación.
 
let postsByMostPopular = ref.child("posts").queryOrdered(byChild: "metrics/views")

C objetivo

Nota: Este producto de Firebase no está disponible en el destino del clip de aplicación.
 
FIRDatabaseQuery *postsByMostPopular = [[ref child:@"posts"] queryOrderedByChild:@"metrics/views"];

Para obtener más información sobre cómo se ordenan otros tipos de datos, consulte Cómo se ordenan los datos de la consulta .

Filtrar datos

Para filtrar datos, puede combinar cualquiera de los métodos de límite o rango con un método de ordenar por al crear una consulta.

Método Uso
queryLimitedToFirst Establece el número máximo de elementos que se devolverán desde el principio de la lista ordenada de resultados.
queryLimitedToLast Establece el número máximo de elementos que se devolverán desde el final de la lista ordenada de resultados.
queryStartingAtValue Devuelve elementos mayores o iguales a la clave o valor especificado, según el método de ordenamiento elegido.
queryStartingAfterValue Devuelve elementos mayores que la clave o el valor especificado, según el método de ordenación elegido.
queryEndingAtValue Devuelve elementos menores o iguales a la clave o valor especificado, según el método de ordenamiento elegido.
queryEndingBeforeValue Devuelve elementos inferiores a la clave o valor especificado, según el método de ordenación elegido.
queryEqualToValue Devuelve elementos iguales a la clave o valor especificado, según el método de ordenamiento elegido.

A diferencia de los métodos de orden por, puede combinar múltiples funciones de límite o rango. Por ejemplo, puede combinar los métodos queryStartingAtValue y queryEndingAtValue para limitar los resultados a un rango de valores específico.

Limitar el número de resultados.

Puede utilizar los métodos queryLimitedToFirst y queryLimitedToLast para establecer un número máximo de elementos secundarios que se sincronizarán para una devolución de llamada determinada. Por ejemplo, si usa queryLimitedToFirst para establecer un límite de 100, inicialmente solo recibirá hasta 100 devoluciones de llamada FIRDataEventTypeChildAdded . Si tiene menos de 100 elementos almacenados en su base de datos de Firebase, se activa una devolución de llamada FIRDataEventTypeChildAdded para cada elemento.

A medida que los elementos cambian, recibe devoluciones de llamada FIRDataEventTypeChildAdded para los elementos que ingresan a la consulta y devoluciones de llamada FIRDataEventTypeChildRemoved para los elementos que salen de ella, de modo que el número total se mantenga en 100.

El siguiente ejemplo demuestra cómo una aplicación de blogs de ejemplo podría recuperar una lista de las 100 publicaciones más recientes de todos los usuarios:

Rápido

Nota: Este producto de Firebase no está disponible en el destino del clip de aplicación.
// 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 objetivo

Nota: Este producto de Firebase no está disponible en el destino del clip de aplicación.
// Last 100 posts, these are automatically the 100 most recent
// due to sorting by push() keys
FIRDatabaseQuery *recentPostsQuery = [[self.ref child:@"posts"] queryLimitedToFirst:100];

Filtrar por clave o valor

Puede utilizar queryStartingAtValue , queryStartingAfterValue , queryEndingAtValue , queryEndingBeforeValue y queryEqualToValue para elegir puntos de inicio, finalización y equivalencia arbitrarios para las consultas. Esto puede resultar útil para paginar datos o buscar elementos con elementos secundarios que tengan un valor específico.

Cómo se ordenan los datos de la consulta

Esta sección explica cómo se ordenan los datos mediante cada uno de los métodos de ordenación en la clase FIRDatabaseQuery .

queryOrderedByKey

Cuando se utiliza queryOrderedByKey para ordenar los datos, los datos se devuelven en orden ascendente por clave.

  1. Los niños con una clave que se puede analizar como un entero de 32 bits aparecen primero, ordenados en orden ascendente.
  2. Los niños con un valor de cadena como clave vienen a continuación, ordenados lexicográficamente en orden ascendente.

queryOrderedByValue

Cuando se utiliza queryOrderedByValue , los elementos secundarios se ordenan por su valor. Los criterios de orden son los mismos que en queryOrderedByChild , excepto que se utiliza el valor del nodo en lugar del valor de una clave secundaria especificada.

queryOrderedByChild

Cuando se utiliza queryOrderedByChild , los datos que contienen la clave secundaria especificada se ordenan de la siguiente manera:

  1. Los niños con un valor nil para la clave secundaria especificada son lo primero.
  2. Los niños con un valor false para la clave secundaria especificada son los siguientes. Si varios hijos tienen un valor false , se ordenan lexicográficamente por clave.
  3. Los niños con un valor true para la clave secundaria especificada son los siguientes. Si varios hijos tienen un valor true , se ordenan lexicográficamente por clave.
  4. Los niños con un valor numérico vienen a continuación, ordenados en orden ascendente. Si varios hijos tienen el mismo valor numérico para el nodo hijo especificado, se ordenan por clave.
  5. Las cadenas van después de los números y están ordenadas lexicográficamente en orden ascendente. Si varios hijos tienen el mismo valor para el nodo hijo especificado, se ordenan lexicográficamente por clave.
  6. Los objetos van al final y se ordenan lexicográficamente por clave en orden ascendente.

Separar oyentes

Los observadores no dejan de sincronizar datos automáticamente cuando sales de un ViewController . Si un observador no se elimina correctamente, continúa sincronizando datos con la memoria local y retendrá cualquier objeto capturado en el cierre del controlador de eventos, lo que puede provocar pérdidas de memoria. Cuando ya no sea necesario un observador, elimínelo pasando el FIRDatabaseHandle asociado al método removeObserverWithHandle .

Cuando agrega un bloque de devolución de llamada a una referencia, se devuelve un FIRDatabaseHandle . Estos identificadores se pueden utilizar para eliminar el bloqueo de devolución de llamada.

Si se han agregado varios oyentes a una referencia de base de datos, se llama a cada oyente cuando se genera un evento. Para detener la sincronización de datos en esa ubicación, debe eliminar todos los observadores en una ubicación llamando al método removeAllObservers .

Llamar a removeObserverWithHandle o removeAllObservers en un oyente no elimina automáticamente los oyentes registrados en sus nodos secundarios; También debes realizar un seguimiento de esas referencias o identificadores para eliminarlos.

Próximos pasos