Проблема заключается в том, что вы смешиваете Basi c Cursor Pagination с Query Cursor Pagination в вашей реализации.
Basi c Разбиение курсора Часть вашего кода (вплоть до first.addSnapshotListener
) верна и будет выполнять каждый раз, возвращая все больше и больше данных на карту каждый раз, когда вы вызываете функцию и разрешаете ее, однако часть Query Cursor Pagination никогда не будет вызываться, поэтому вы можете полностью удалить эту часть из своей реализации.
Таким образом, ваш код должен выглядеть следующим образом:
func fetchCollection<Collection: CollectionProtocol>(lastSnapshot: DocumentSnapshot?, query: Query, completion: @escaping (Result<[Collection], Error>) -> Void) {
var first = query.limit(to: 1)
if let lastSnapshot = lastSnapshot {
first = query.start(afterDocument: lastSnapshot)
}
first.getDocuments() { (querySnapshot, error) in
if let snapshot = querySnapshot {
// print(snapshot.metadata.isFromCache)
completion(.success(snapshot.documents.map { document -> Collection in
return Collection(document: document)
}))
} else if let error = error {
completion(.failure(error))
}
}
}
NOTE : Вы также можете добавить .limit(to:1)
к вашей проверке lastSnapshot, поскольку, как и сейчас, она будет извлекать все документы, конечно, если это ваш предполагаемый лог c, игнорируйте эту заметку.
РЕДАКТИРОВАТЬ:
Если вы хотите использовать разбиение на страницы курсора запроса, вы можете следовать этому примеру, где слушатель находится вне функции fetchCollection и выполняется каждый раз, когда getDocuments () запускается и монтирует должен быть выполнен новый запрос:
//initial state of your app
var results = "nil";
//initial query
var query = db.collection("foo").document("bar").limit(to: 1);
//everytime you need more data fetched and on database updates to your snapshot this will be triggered
query.addSnapshotListener { querySnapshot, error in
guard let snapshot = querySnapshot else {
print("Error fetching snapshots: \(error!)")
return
}
snapshot.documentChanges.forEach {
// update data
}
let next = db.collection("foo").document("bar").start(afterDocument: result.last!).limit(to: 1);
query = next;
};
//initial load of data
fetchCollection();
//simply executes the query
func fetchCollection() {
query.getDocuments { (document, error) in
if let document = document, document.exists {
if(result == "nil"){
result = document.data().map();
}else{
result.map({ document.data() })
}
} else {
print("Document does not exist")
}
}
}
ПРИМЕЧАНИЕ : имейте в виду, что это непроверенный пример, но он может быть хорошим началом укажите, что вам нужно в вашем приложении. Кроме того, я использую эту документацию для обновлений в режиме реального времени на приемнике, вы можете найти дополнительную информацию по этой ссылке.