Как получить объект FIRDatabaseReference
Чтобы читать или записывать данные в базу данных, вам понадобится экземпляр FIRDatabaseReference:
Swift
var ref: DatabaseReference! ref = Database.database().reference()
Objective-C
@property (strong, nonatomic) FIRDatabaseReference *ref; self.ref = [[FIRDatabase database] reference];
Как читать и писать списки
Добавить данные в список
Используйте метод childByAutoId, чтобы добавить данные в список в многопользовательских приложениях. Метод childByAutoId создает уникальный ключ каждый раз, когда в указанную ссылку Firebase добавляется новый дочерний элемент. Используя автоматически созданные ключи для каждого нового элемента в списке, несколько клиентов могут одновременно добавлять дочерние элементы в одно и то же местоположение без конфликтов записи. Уникальный ключ, созданный childByAutoId, основан на временной метке, поэтому элементы списка автоматически упорядочиваются по хронологии.
Вы можете использовать ссылку на новые данные, возвращенные методом childByAutoId, чтобы получить значение автоматически созданного ключа дочернего объекта или задать данные для дочернего объекта.
При вызове функции getKey для ссылки на объект childByAutoId возвращается автоматически созданный ключ.
Эти автоматически созданные ключи можно использовать, чтобы упростить структуру данных. Подробнее о веерной рассылке данных…
Как отслеживать дочерние события
События, связанные с дочерними элементами, запускаются в ответ на определенные операции, выполняемые с дочерними элементами узла, например добавление нового дочернего элемента с помощью метода childByAutoId или обновление дочернего элемента с помощью метода updateChildValues.
| Тип события | Типичное использование |
|---|---|
FIRDataEventTypeChildAdded |
Получать списки объектов или слушать, как добавляются объекты в список. Это событие вызывается один раз для каждого существующего дочернего элемента, а затем каждый раз, когда в указанный путь добавляется новый дочерний элемент. Слушателю передается снимок с данными нового дочернего объекта. |
FIRDataEventTypeChildChanged |
отслеживать изменения элементов в списке; Это событие активируется при каждом изменении дочернего узла. Это относится и к любым изменениям дочерних узлов. Снимок, переданный прослушивателю событий, содержит обновленные данные о ребенке. |
FIRDataEventTypeChildRemoved |
Слушайте, как элементы удаляются из списка. Это событие активируется, когда удаляется дочерний элемент.Снимок, переданный в блок обратного вызова, содержит данные удаленного дочернего элемента. |
FIRDataEventTypeChildMoved |
Слушать изменения порядка элементов в нумерованном списке.
Это событие активируется, когда обновление приводит к изменению порядка дочерних элементов. Она используется с данными, упорядоченными по queryOrderedByChild
или queryOrderedByValue.
|
Каждый из этих методов может быть полезен для отслеживания изменений в определенном узле базы данных. Например, приложение для ведения блогов в социальных сетях может использовать эти методы вместе, чтобы отслеживать активность в комментариях к записи, как показано ниже:
Swift
// 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
// 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, который можно перебрать в цикле для доступа к отдельным дочерним элементам.
Даже если по запросу найден только один результат, снимок все равно представляет собой список, в котором содержится один элемент. Чтобы получить доступ к элементу, нужно перебрать результаты в цикле:
Swift
_commentsRef.observe(.value) { snapshot in for child in snapshot.children { ... } }
Objective-C
[_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, возникнет ошибка.
В примере ниже показано, как получить список лучших записей пользователя, отсортированных по количеству звезд.
Swift
// My top posts by number of stars let myTopPostsQuery = ref.child("user-posts").child(getUid()).queryOrdered(byChild: "starCount")
Objective-C
// My top posts by number of stars FIRDatabaseQuery *myTopPostsQuery = [[[self.ref child:@"user-posts"] child:[super getUid]] queryOrderedByChild:@"starCount"];
Этот запрос извлекает записи пользователя из пути в базе данных на основе его идентификатора, упорядочивая их по количеству полученных звезд. Этот метод использования идентификаторов в качестве ключей индекса называется разветвлением данных. Подробнее о нем можно прочитать в статье Структура базы данных.
Вызов метода 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",
}
},В этом случае мы можем отсортировать элементы списка по значениям, вложенным в ключ metrics, указав относительный путь к вложенному дочернему элементу в вызове queryOrderedByChild.
Swift
let postsByMostPopular = ref.child("posts").queryOrdered(byChild: "metrics/views")
Objective-C
FIRDatabaseQuery *postsByMostPopular = [[ref child:@"posts"] queryOrderedByChild:@"metrics/views"];
Подробнее о том, как упорядочиваются другие типы данных, рассказывается в статье Как упорядочиваются данные запросов.
Фильтрация данных
Чтобы отфильтровать данные, при создании запроса можно сочетать любые методы ограничения или диапазона с методом сортировки.
| Метод | Использование |
|---|---|
queryLimitedToFirst |
Устанавливает максимальное количество элементов, которые будут возвращены из начала упорядоченного списка результатов. |
queryLimitedToLast |
Задает максимальное количество объектов, которые будут возвращены из конца упорядоченного списка результатов. |
queryStartingAtValue |
Возвращает элементы, значение ключа или значение которых больше или равно указанному, в зависимости от выбранного метода сортировки. |
queryStartingAfterValue |
Возвращает объекты, значения ключей или значения которых больше указанного, в зависимости от выбранного метода сортировки. |
queryEndingAtValue |
Возвращает объекты, значение ключа или атрибута которых меньше или равно указанному, в зависимости от выбранного метода сортировки. |
queryEndingBeforeValue |
Возвращает объекты, значение ключа или атрибута которых меньше указанного, в зависимости от выбранного метода сортировки. |
queryEqualToValue |
Возвращает элементы, равные указанному ключу или значению, в зависимости от выбранного метода сортировки. |
В отличие от методов сортировки, вы можете комбинировать несколько функций ограничения или диапазона.
Например, вы можете объединить методы queryStartingAtValue и queryEndingAtValue, чтобы ограничить результаты определенным диапазоном значений.
Как ограничить количество результатов
Вы можете использовать методы queryLimitedToFirst и queryLimitedToLast, чтобы задать максимальное количество дочерних элементов, которые будут синхронизированы для определенного обратного вызова. Например, если вы используете queryLimitedToFirst, чтобы задать ограничение в 100, то сначала получите не более 100 обратных вызовов FIRDataEventTypeChildAdded. Если в базе данных Firebase хранится менее 100 объектов, обратный вызов FIRDataEventTypeChildAdded будет выполняться для каждого из них.
При изменении объектов вы получаете обратные вызовы FIRDataEventTypeChildAdded для объектов, которые входят в запрос, и обратные вызовы FIRDataEventTypeChildRemoved для объектов, которые выходят из него, чтобы общее количество оставалось равным 100.
В примере ниже показано, как приложение для ведения блогов может получить список из 100 последних записей всех пользователей:
Swift
// 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
// Last 100 posts, these are automatically the 100 most recent // due to sorting by push() keys FIRDatabaseQuery *recentPostsQuery = [[self.ref child:@"posts"] queryLimitedToFirst:100];
Фильтр по ключу или значению
Вы можете использовать queryStartingAtValue, queryStartingAfterValue, queryEndingAtValue, queryEndingBeforeValue и queryEqualToValue, чтобы задать произвольные начальные, конечные и эквивалентные точки для запросов. Это может быть полезно для разбивки данных на страницы или поиска объектов с дочерними элементами, имеющими определенное значение.
Как упорядочиваются данные запроса
В этом разделе рассказывается, как сортируются данные при использовании каждого из методов сортировки в классе FIRDatabaseQuery.
queryOrderedByKey
При использовании функции queryOrderedByKey для сортировки данных они возвращаются в порядке возрастания по ключу.
- Сначала идут дети с ключом, который можно преобразовать в 32-битное целое число, отсортированные по возрастанию.
- Затем идут дети со строковым значением в качестве ключа, отсортированные в лексикографическом порядке по возрастанию.
queryOrderedByValue
При использовании функции queryOrderedByValue дети сортируются по ценности. Критерии сортировки такие же, как в queryOrderedByChild, за исключением того, что вместо значения указанного дочернего ключа используется значение узла.
queryOrderedByChild
При использовании queryOrderedByChild данные, содержащие указанный дочерний ключ, упорядочиваются следующим образом:
- Сначала показываются дети с указанным ключом и значением
nil. - Затем идут дочерние элементы со значением
falseдля указанного дочернего ключа. Если у нескольких дочерних элементов есть значениеfalse, они сортируются лексикографически по ключу. - Затем идут дочерние элементы со значением
trueдля указанного дочернего ключа. Если у нескольких дочерних элементов значениеtrue, они сортируются в лексикографическом порядке по ключу. - Затем идут дочерние элементы с числовыми значениями, отсортированные по возрастанию. Если у нескольких дочерних элементов одно и то же числовое значение для указанного дочернего узла, они сортируются по ключу.
- Строки идут после чисел и сортируются в лексикографическом порядке по возрастанию. Если у нескольких дочерних узлов одно и то же значение, они сортируются в лексикографическом порядке по ключу.
- Объекты идут последними и сортируются в лексикографическом порядке по ключу в порядке возрастания.
Отключить прослушиватели
Наблюдатели не прекращают автоматически синхронизировать данные, когда вы покидаете ViewController. Если наблюдатель не удален должным образом, он продолжает синхронизировать данные с локальной памятью и сохраняет все объекты, захваченные в замыкании обработчика событий, что может привести к утечке памяти. Если наблюдатель больше не нужен, удалите его, передав связанный с ним объект FIRDatabaseHandle методу removeObserverWithHandle.
Когда вы добавляете блок обратного вызова в ссылку, возвращается значение FIRDatabaseHandle.
Эти маркеры можно использовать, чтобы удалить блок обратного вызова.
Если к ссылке на базу данных добавлено несколько прослушивателей, при возникновении события вызывается каждый из них. Чтобы остановить синхронизацию данных в определенном месте, необходимо удалить всех наблюдателей в этом месте, вызвав метод removeAllObservers.
Вызов removeObserverWithHandle или removeAllObservers для прослушивателя не приводит к автоматическому удалению прослушивателей, зарегистрированных в его дочерних узлах. Вам также необходимо отслеживать эти ссылки или дескрипторы, чтобы удалить их.