我有一个从Firestore集合填充的UITableView子类。我一次只抓取20个文档,并且当用户接近已加载数组的末尾时,使用UITableViewDataSourcePrefetching
委托从Firestore获取20个文档的下一个“页面”。
以下是我的代码,几乎可以完美地实现此目标,并在适当的地方省略/混淆。
class MyCustomViewController: UIViewController {
@IBOutlet weak var myCustomTableView: MyCustomTableView!
override func viewDidLoad() {
super.viewDidLoad()
myCustomTableView.query = Firestore.firestore().collection("MyCollection").whereField("foo", isEqualTo: "bar").order(by: "timestamp", descending: true)
myCustomTableView.fetchNextPage()
}
}
extension MyCustomViewController: UITableViewDataSourcePrefetching {
func tableView(_ tableView: UITableView, prefetchRowsAt indexPaths: [IndexPath]) {
guard let tableView = tableView as? MyCustomTableView else {
return
}
tableView.prefetch(indexPaths: indexPaths)
}
}
class MyCustomTableView: UITableView {
var documents = [DocumentSnapshot]()
var query: Query?
let querySize = 20
private var fetchSemaphore = DispatchSemaphore(value: 1)
public func prefetch(indexPaths: [IndexPath]) {
for indexPath in indexPaths {
if indexPath.section >= documents.count - 1 {
fetchNextPage()
return
}
}
}
public func fetchNextPage() {
guard let query = query else {
return
}
guard documents.count % querySize == 0 else {
print("No further pages to fetch.")
return
}
guard fetchSemaphore.wait(timeout: .now()) == .success else { return }
if self.documents.isEmpty {
query.limit(to: querySize).addSnapshotListener { (snapshot, error) in
guard let snapshot = snapshot else {
return
}
self.documents.append(contentsOf: snapshot.documents)
self.reloadData()
self.fetchSemaphore.signal()
}
}
else {
// I think the problem is on this next line
query.limit(to: querySize).start(afterDocument: documents.last!).addSnapshotListener { (snapshot, error) in
guard let snapshot = snapshot else {
return
}
for document in snapshot.documents {
if let index = self.documents.firstIndex(where: { $0.documentID == document.documentID }) {
self.documents[index] = document
}
else {
self.documents.append(document)
}
}
self.reloadData()
self.fetchSemaphore.signal()
}
}
}
}
我想我知道问题出在哪里/在哪里(请参阅fetchNextPage()
中的注释),但我可能是错的。即使我是正确的,我也无法提出解决方案。
我的查询按文档的timestamp
值以降序排序,顾名思义,该值代表创建文档的时间。这意味着在表格视图中,最新文档将显示在顶部,而最旧文档显示在底部。
除...外,一切正常。
问题:创建新文档时,表中的每个项目都将被逐行缩小,因为新文档具有最新的时间戳并将其放置在顶部。很好,除了发生这种情况之外,所有查询快照侦听器(第一个侦听器除外)都不再使用正确的文档开始。最初使用documents.last!
检索的文档快照不再是查询应开始的正确文档。我不知道如何更改现有快照侦听器的startAfter
参数。我找不到任何可用于更改此查询的方法。
同样,这实际上可能并不是我在添加新文档时看到乱序的原因,但我认为是这样。如果有人对如何解决此问题提出建议,我将不胜感激。
我以前到过这里的参考文献:
其他说明:
getDocuments
。在这种情况下,进行近实时更新很重要。indexPath.section
而不是indexPath.row
,这是因为表由许多单行节组成,因此可以在单元格之间放置垂直填充。