我现在正在使用Firestore,并且在分页方面有一点问题。
基本上,我有一个集合(假设10个条目),其中每个项目都有一些数据和时间戳。
现在,我将获取前3项内容如下:
Firestore.firestore()
.collection("collectionPath")
.order(by: "timestamp", descending: true)
.limit(to: 3)
.addSnapshotListener(snapshotListener())在快照监听器中,我保存快照中的最后一个文档,以便将其用作下一页的起点。
因此,在某个时候,我将请求下一页的项目如下:
Firestore.firestore()
.collection("collectionPath")
.order(by: "timestamp", descending: true)
.start(afterDocument: lastDocument)
.limit(to: 3)
.addSnapshotListener(snapshotListener2()) // Note that this is a new snapshot listener, I don't know how I could reuse the first one现在,我的前面有从索引0到索引5(总共6)的项。整洁!
如果索引4处的文档现在将其时间戳更新为整个集合的最新时间戳,则情况开始下降。
请记住,时间戳决定了它的位置,因为订单子句!
我期望发生的是,在应用了这些更改之后,我仍然显示了6个项目(并且仍然按它们的时间戳订购)。
所发生的情况是,在应用更改之后,我只剩下5个项,因为从第一个快照中推送的项不会自动添加到第二个快照中。
我是不是漏掉了与Firestore分页有关的东西?
编辑:根据要求,我在这里发布了更多代码:
这是我返回快照侦听器的函数。好吧,还有我用来请求第一页和第二页的两种方法。
private func snapshotListener() -> FIRQuerySnapshotBlock {
let index = self.index
return { querySnapshot, error in
guard let snap = querySnapshot, error == nil else {
log.error(error)
return
}
// Save the last doc, so we can later use pagination to retrieve further chats
if snap.count == self.limit {
self.lastDoc = snap.documents.last
} else {
self.lastDoc = nil
}
let offset = index * self.limit
snap.documentChanges.forEach() { diff in
switch diff.type {
case .added:
log.debug("added chat at index: \(diff.newIndex), offset: \(offset)")
self.tVHandler.dataManager.insert(item: Chat(dictionary: diff.document.data() as NSDictionary), at: IndexPath(row: Int(diff.newIndex) + offset, section: 0), in: nil)
case .removed:
log.debug("deleted chat at index: \(diff.oldIndex), offset: \(offset)")
self.tVHandler.dataManager.remove(itemAt: IndexPath(row: Int(diff.oldIndex) + offset, section: 0), in: nil)
case .modified:
if diff.oldIndex == diff.newIndex {
log.debug("updated chat at index: \(diff.oldIndex), offset: \(offset)")
self.tVHandler.dataManager.update(item: Chat(dictionary: diff.document.data() as NSDictionary), at: IndexPath(row: Int(diff.oldIndex) + offset, section: 0), in: nil)
} else {
log.debug("moved chat at index: \(diff.oldIndex), offset: \(offset) to index: \(diff.newIndex), offset: \(offset)")
self.tVHandler.dataManager.move(item: Chat(dictionary: diff.document.data() as NSDictionary), from: IndexPath(row: Int(diff.oldIndex) + offset, section: 0), to: IndexPath(row: Int(diff.newIndex) + offset, section: 0), in: nil)
}
}
}
self.tableView?.reloadData()
}
}因此,我再次询问,是否可以有一个快照侦听器来侦听我从Firestore请求的多个页面中的更改。
发布于 2017-11-16 11:46:48
发布于 2018-12-24 13:27:53
我今天遇到了同样的用例,并且在目标C客户机中成功地实现了一个工作解决方案。下面是算法,如果有人想在他们的程序中应用,我会非常感激谷歌云防火墙团队能把我的解决方案放在他们的页面上。
用例:允许分页最近聊天的长列表的特性,以及附加实时侦听器更新列表的选项,以便与最上面的最新消息进行聊天。
解决方案:--这可以通过使用分页逻辑来实现,就像我们对其他长列表所做的那样,并附加限制为1的实时侦听器:
步骤1:在页面加载中,使用分页查询获取聊天,如下所示:
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
[self fetchChats];
}
-(void)fetchChats {
__weak typeof(self) weakSelf = self;
FIRQuery *paginateChatsQuery = [[[self.db collectionWithPath:MAGConstCollectionNameChats]queryOrderedByField:MAGConstFieldNameTimestamp descending:YES]queryLimitedTo:MAGConstPageLimit];
if(self.arrChats.count > 0){
FIRDocumentSnapshot *lastChatDocument = self.arrChats.lastObject;
paginateChatsQuery = [paginateChatsQuery queryStartingAfterDocument:lastChatDocument];
}
[paginateChatsQuery getDocumentsWithCompletion:^(FIRQuerySnapshot * _Nullable snapshot, NSError * _Nullable error) {
if (snapshot == nil) {
NSLog(@"Error fetching documents: %@", error);
return;
}
///2. Observe chat updates if not attached
if(weakSelf.chatObserverState == ChatObserverStateNotAttached) {
weakSelf.chatObserverState = ChatObserverStateAttaching;
[weakSelf observeChats];
}
if(snapshot.documents.count < MAGConstPageLimit) {
weakSelf.noMoreData = YES;
}
else {
weakSelf.noMoreData = NO;
}
[weakSelf.arrChats addObjectsFromArray:snapshot.documents];
[weakSelf.tblVuChatsList reloadData];
}];
}步骤2:在成功回调"fetchAlerts“方法时,只将观察者附加一次实时更新,并将限制设置为1。
-(void)observeChats {
__weak typeof(self) weakSelf = self;
self.chatsListener = [[[[self.db collectionWithPath:MAGConstCollectionNameChats]queryOrderedByField:MAGConstFieldNameTimestamp descending:YES]queryLimitedTo:1]addSnapshotListener:^(FIRQuerySnapshot * _Nullable snapshot, NSError * _Nullable error) {
if (snapshot == nil) {
NSLog(@"Error fetching documents: %@", error);
return;
}
if(weakSelf.chatObserverState == ChatObserverStateAttaching) {
weakSelf.chatObserverState = ChatObserverStateAttached;
}
for (FIRDocumentChange *diff in snapshot.documentChanges) {
if (diff.type == FIRDocumentChangeTypeAdded) {
///New chat added
NSLog(@"Added chat: %@", diff.document.data);
FIRDocumentSnapshot *chatDoc = diff.document;
[weakSelf handleChatUpdates:chatDoc];
}
else if (diff.type == FIRDocumentChangeTypeModified) {
NSLog(@"Modified chat: %@", diff.document.data);
FIRDocumentSnapshot *chatDoc = diff.document;
[weakSelf handleChatUpdates:chatDoc];
}
else if (diff.type == FIRDocumentChangeTypeRemoved) {
NSLog(@"Removed chat: %@", diff.document.data);
}
}
}];
}步骤3.在侦听器回调上,检查文档更改,只处理FIRDocumentChangeTypeAdded和FIRDocumentChangeTypeModified事件,忽略FIRDocumentChangeTypeRemoved事件。为此,我们为FIRDocumentChangeTypeAdded和FIRDocumentChangeTypeModified事件调用FIRDocumentChangeTypeAdded方法,其中我们首先尝试从本地列表中找到匹配的聊天文档,如果它存在,我们将从列表中删除它,然后将从侦听器回调中接收到的新文档添加到列表的开头。
-(void)handleChatUpdates:(FIRDocumentSnapshot *)chatDoc {
NSInteger chatIndex = [self getIndexOfMatchingChatDoc:chatDoc];
if(chatIndex != NSNotFound) {
///Remove this object
[self.arrChats removeObjectAtIndex:chatIndex];
}
///Insert this chat object at the beginning of the array
[self.arrChats insertObject:chatDoc atIndex:0];
///Refresh the tableview
[self.tblVuChatsList reloadData];
}
-(NSInteger)getIndexOfMatchingChatDoc:(FIRDocumentSnapshot *)chatDoc {
NSInteger chatIndex = 0;
for (FIRDocumentSnapshot *chatDocument in self.arrChats) {
if([chatDocument.documentID isEqualToString:chatDoc.documentID]) {
return chatIndex;
}
chatIndex++;
}
return NSNotFound;
}步骤4.重新加载表视图以查看更改。
发布于 2019-07-26 04:57:54
我的解决方案是创建一个保持器查询-侦听器来观察从第一个查询中删除的条目,每次出现新消息时我们都会更新它。
https://stackoverflow.com/questions/47182780
复制相似问题