You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift聊天应用问题:底部显示最新消息时无法加载更多

问题根源

首次查询用.order(by: TIMESTAMP, descending: false).limit(toLast:5)获取的是最新的5条消息,此时lastDocument是这5条中时间戳最大的(最新的那条)。加载更多时用start(afterDocument: lastDocument),相当于请求时间戳比最新消息还晚的消息,自然查不到任何数据,导致TableView无法填充。


修复方案

要实现「最新消息在底部+加载旧消息正常」,可以通过两种思路调整逻辑:

方案一:基于升序查询直接加载历史消息

核心逻辑

首次加载取最新的5条消息,加载更多时请求比当前数组中最早消息更早的历史消息,并将新消息插入数组头部以保持旧→新的顺序。

修改后代码

func fetchChatMessages() {
    fetchMoreDocs = true
    var query: Query!
    
    if messages.isEmpty {
        // 首次加载:获取最新的5条消息(升序取最后5条)
        query = MESSAGES_COLLECTION.document(currentUID!).collection(user.memberId)
            .order(by: TIMESTAMP, descending: false)
            .limit(toLast: 5)
    } else {
        // 加载更多:获取比当前最早消息更早的5条
        guard let firstMessageDoc = messages.first?.documentSnapshot else {
            fetchMoreDocs = false
            return
        }
        query = MESSAGES_COLLECTION.document(currentUID!).collection(user.memberId)
            .order(by: TIMESTAMP, descending: false)
            .start(beforeDocument: firstMessageDoc)
            .limit(to: 5)
    }
    
    query.addSnapshotListener { (snapshot, error) in
        if let error = error {
            print("Error..\(error.localizedDescription)")
            self.fetchMoreDocs = false
            return
        } else if snapshot!.isEmpty {
            self.fetchMoreDocs = false
            return
        } else {
            let newMessages = Message.parseData(snapshot: snapshot)
            // 历史消息插入数组头部,保持旧→新顺序
            self.messages.insert(contentsOf: newMessages, at: 0)
            DispatchQueue.main.async {
                self.chatRoomTV.reloadData()
                // 仅首次加载后滚动到底部,加载更多时保留当前滚动位置
                if self.messages.count == newMessages.count {
                    self.scrollToBottom()
                }
                self.fetchMoreDocs = false
            }
        }
    }
}

配套调整

确保Message模型保存Firestore的DocumentSnapshot,用于加载更多时定位:

class Message {
    var documentSnapshot: DocumentSnapshot?
    // 其他消息属性(内容、发送者等)
    
    static func parseData(snapshot: QuerySnapshot?) -> [Message] {
        var messages = [Message]()
        guard let docs = snapshot?.documents else { return messages }
        for doc in docs {
            let message = Message()
            // 解析消息内容、发送者等字段...
            message.documentSnapshot = doc
            messages.append(message)
        }
        return messages
    }
}

方案二:复用降序查询逻辑,反转数组调整顺序

核心逻辑

用你之前验证过的降序查询加载消息,通过反转数组将消息顺序改为旧→新,让最新消息落在数组最后(对应TableView底部)。

修改后代码

func fetchChatMessages() {
    fetchMoreDocs = true
    var query: Query!
    
    if messages.isEmpty {
        query = MESSAGES_COLLECTION.document(currentUID!).collection(user.memberId)
            .order(by: TIMESTAMP, descending: true)
            .limit(to: 5)
    } else {
        guard let lastMessageDoc = messages.last?.documentSnapshot else {
            fetchMoreDocs = false
            return
        }
        query = MESSAGES_COLLECTION.document(currentUID!).collection(user.memberId)
            .order(by: TIMESTAMP, descending: true)
            .start(afterDocument: lastMessageDoc)
            .limit(to: 5)
    }
    
    query.addSnapshotListener { (snapshot, error) in
        if let error = error {
            print("Error..\(error.localizedDescription)")
            self.fetchMoreDocs = false
            return
        } else if snapshot!.isEmpty {
            self.fetchMoreDocs = false
            return
        } else {
            var newMessages = Message.parseData(snapshot: snapshot)
            // 反转数组,将降序结果转为旧→新顺序
            newMessages.reverse()
            // 首次加载直接赋值,加载更多追加到数组末尾
            if self.messages.isEmpty {
                self.messages = newMessages
            } else {
                self.messages.append(contentsOf: newMessages)
            }
            DispatchQueue.main.async {
                self.chatRoomTV.reloadData()
                self.scrollToBottom()
                self.fetchMoreDocs = false
            }
        }
    }
}

内容的提问来源于stack exchange,提问作者Eddie

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 17:15:43