#ios #swift #firebase #google-cloud-firestore
#iOS #быстрый #firebase #google-облако-firestore #swift
Вопрос:
Я создаю функцию чата для своего приложения с помощью Firestore. Я использую limit(toLast:)
поскольку я извлекаю данные на основе метки времени, этот метод выдает мне последние сообщения, сохраненные в моей базе данных. Но это доставляет мне проблемы при попытке получить снимок / документы до этого для загрузки старых сообщений. Вот мой код:
fileprivate func paginateFetchMessages() {
var query: Query!
if let nextStartingSnap = self.lastDocumentSnapshot {
query = DBCall.fireRef.collection("friendMessages")
.document(currentUID)
.collection(friendUID)
.order(by: "timestamp").limit(toLast: 5).start(afterDocument: nextStartingSnap)
} else {
query = DBCall.fireRef.collection("friendMessages")
.document(currentUID)
.collection(friendUID)
.order(by: "timestamp").limit(toLast: 5)
}
query.addSnapshotListener { querySnapshot, error in
guard let snapshot = querySnapshot else {
print("Error fetching snapshots: (error!)")
return
}
guard let lastSnap = snapshot.documents.last else {
self.refreshControl.endRefreshing()
return
}
print(snapshot.documents)
self.lastDocumentSnapshot = lastSnap
snapshot.documentChanges.forEach({ (change) in
if change.type == .added {
let data = change.document.data()
let text = data["message"] as! String
let fromID = data["fromID"] as! String
let messageID = data["messageId"] as? String ?? ""
let isRead = data["isRead"] as? Bool ?? false
let timestamp = data["timestamp"] as! Timestamp
let user = MessageKitUser(senderId: fromID, displayName: "")
let message = MessageKitText(text: text, user: user, messageId: messageID, date: Date(), isRead: isRead, firDate: timestamp )
self.insertMessage(message)
self.refreshControl.endRefreshing()
}
})
}
}
Когда я использую snapshot.documents.last
, ничего не возвращается, потому что я изначально выбираю «последние» документы. Мне нужно получать 5 снимков до последнего, каждый раз при разбивке на страницы.
Дайте мне знать, если это не имеет смысла и у вас есть вопросы. Спасибо!!
Ответ №1:
Допустим, у вас есть 10 документов:
[1,2,3,4,5,6,7,8,9,10]
Ваш limitToLast(5)
получит:
[6,7,8,9,10]
Поскольку вы используете start(afterDocument:
, Firestore запускается после document 6
, а это не то, что вы хотите. Вместо этого вы хотите, чтобы end(beforeDocument:
:
query = DBCall.fireRef.collection("friendMessages")
.document(currentUID)
.collection(friendUID)
.order(by: "timestamp")
.end(beforeDocument: nextStartingSnap)
.limit(toLast: 5)
Я также переворачиваю limit(toLast:
и end(beforeDocument:
. Это не влияет на результаты, но для меня читается немного проще — поскольку Firestore в значительной степени обрабатывает ваш запрос:
- Он загружает индекс на
timestamp
. - Это отключило все, начиная с
nextStartingSnap
этого момента. - Затем он возвращает последние 5 документов, которые остаются в результате.
Комментарии:
1. Небольшое предупреждение: end (до того, как документу потребуется обратный индекс — в сообщении об ошибке будет указана ссылка для его создания
2. Большое вам спасибо @Frank, это то, что мне было нужно. Все, что мне нужно было сделать дальше, это изменить
snapshot.documents.last
наsnapshot.documents.first
, и я получил правильный результат.3. Хороший момент. Прокрутка назад по-прежнему сбивает меня с толку большую часть времени, но это не вина API. 🙂