Получение 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 |
Упорядочивает результаты по значению указанного дочернего ключа или вложенного дочернего пути. |
Одновременно можно использовать только один способ сортировки. Если вызвать способ сортировки несколько раз в одном запросе, возникнет ошибка.
В следующем примере показано, как получить список лучших записей пользователя, отсортированных по количеству звезд:
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 для прослушивателя не удаляет автоматически прослушиватели, зарегистрированные в его дочерних узлах. Чтобы удалить их, вам также необходимо отслеживать эти ссылки или дескрипторы.