首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >固定按压数据+快照侦听器

固定按压数据+快照侦听器
EN

Stack Overflow用户
提问于 2017-11-08 14:54:31
回答 4查看 13.9K关注 0票数 18

我现在正在使用Firestore,并且在分页方面有一点问题。

基本上,我有一个集合(假设10个条目),其中每个项目都有一些数据和时间戳。

现在,我将获取前3项内容如下:

代码语言:javascript
复制
Firestore.firestore()
    .collection("collectionPath")
    .order(by: "timestamp", descending: true)
    .limit(to: 3)
    .addSnapshotListener(snapshotListener())

在快照监听器中,我保存快照中的最后一个文档,以便将其用作下一页的起点。

因此,在某个时候,我将请求下一页的项目如下:

代码语言:javascript
复制
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分页有关的东西?

编辑:根据要求,我在这里发布了更多代码:

这是我返回快照侦听器的函数。好吧,还有我用来请求第一页和第二页的两种方法。

代码语言:javascript
复制
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请求的多个页面中的更改。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2017-11-16 11:46:48

嗯,我联系过Firebase Google Group的人寻求帮助,他们告诉我我的用例还没有被支持。

感谢加藤理查森关心我的问题!

任何对详细信息感兴趣的人,请参阅此线程

票数 6
EN

Stack Overflow用户

发布于 2018-12-24 13:27:53

我今天遇到了同样的用例,并且在目标C客户机中成功地实现了一个工作解决方案。下面是算法,如果有人想在他们的程序中应用,我会非常感激谷歌云防火墙团队能把我的解决方案放在他们的页面上。

用例:允许分页最近聊天的长列表的特性,以及附加实时侦听器更新列表的选项,以便与最上面的最新消息进行聊天。

解决方案:--这可以通过使用分页逻辑来实现,就像我们对其他长列表所做的那样,并附加限制为1的实时侦听器:

步骤1:在页面加载中,使用分页查询获取聊天,如下所示:

代码语言:javascript
复制
- (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。

代码语言:javascript
复制
-(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方法,其中我们首先尝试从本地列表中找到匹配的聊天文档,如果它存在,我们将从列表中删除它,然后将从侦听器回调中接收到的新文档添加到列表的开头。

代码语言:javascript
复制
-(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.重新加载表视图以查看更改。

票数 4
EN

Stack Overflow用户

发布于 2019-07-26 04:57:54

我的解决方案是创建一个保持器查询-侦听器来观察从第一个查询中删除的条目,每次出现新消息时我们都会更新它。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/47182780

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档