ios - 如何根据日期(部分)对 UITableView(聊天气泡)中的消息进行分组?

标签 ios swift firebase uitableview

我有一个聊天应用程序。一切正常,除了当我试图根据消息的日期将聊天消息分组时。第一次加载 chatController 时,一切都很好地获取并准确分组,但是在发送或接收新消息和 tableView 重新加载的那一刻,一切都被复制了(带有行的部分被一次又一次地复制)

所以我有这样的结构或数据模型:

struct Chats {
    let text, fromId, toId: String
    let isIncoming: Bool
    let date: Date

    init(dictionary: [String:Any]) {
        self.text = dictionary["text"] as? String ?? ""
        self.fromId = dictionary["fromId"] as? String ?? ""
        self.toId = dictionary["toId"] as? String ?? ""
        self.date = dictionary["date"] as? Date ?? Date()
        self.isIncoming = Auth.auth().currentUser?.uid != self.fromId
    }
}

这是我试过的:

var messagesFromServer = [Chats]()
var chatMessages = [[Chats]]()

override func viewDidLoad() {
        super.viewDidLoad()
        setupViews()
        fetchMessages()
    }

   fileprivate func fetchMessages(){
        guard let currentUid = Auth.auth().currentUser?.uid else {return}
        let query = Firestore.firestore().collection("connections").document(currentUid).collection(connection.uid).order(by: "date")

        query.addSnapshotListener { (snapshot, error) in
            if let error = error{
                ProgressHUD.showError("Something went wrong. \(error.localizedDescription)")
                return
            }
            snapshot?.documentChanges.forEach({ (change) in
                if change.type == .added{
                    let dictionary = change.document.data()
                    self.messagesFromServer.append(.init(dictionary: dictionary))
                }
            })
            self.attemptToAssembleGroupedMessages { (assembled) in
                if assembled{
                    self.tableView.reloadData()
                }
            }
        }
    }

    fileprivate func attemptToAssembleGroupedMessages(completion: (Bool) -> ()){
        let groupedMessages = Dictionary(grouping: messagesFromServer) { (element) -> Date in
            return element.date.reduceToMonthDayYear()
        }

        // provide a sorting for the keys
        let sortedKeys = groupedMessages.keys.sorted()
        sortedKeys.forEach { (key) in
            let values = groupedMessages[key]
            chatMessages.append(values ?? [])
            let assembled: Bool = true
            completion(assembled)
        }
    }

我所做的解释: 基本上我访问了数据库并将所有消息和数据存储到变量 messagesFromServer 中。这很好用。当我尝试根据日期将此变量的内容分组到一个新变量 chatMessages 时,会出现问题(这是使用函数 attempToAssembleGroupMessages 完成的)

如果你们有兴趣查看 TableView 是如何获取数据的,这里是代码:

extension ChatController: UITableViewDelegate, UITableViewDataSource{

    //How many sections
    func numberOfSections(in tableView: UITableView) -> Int {
        return chatMessages.count
    }

    //What is the view in each of these sections
    func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
        if let firstMessageInSection = chatMessages[section].first {
            let dateFormatter = DateFormatter()
            dateFormatter.dateFormat = "MM/dd/yyyy"
            let dateString = dateFormatter.string(from: firstMessageInSection.date)

            let label = ViewForDateHeaderLabel()
            label.text = dateString

            let containerView = UIView()
            containerView.addSubview(label)
            label.centerXAnchor.constraint(equalTo: containerView.centerXAnchor).isActive = true
            label.centerYAnchor.constraint(equalTo: containerView.centerYAnchor).isActive = true

            return containerView
        }
        return nil
    }

    //What is the height of the view in each of these Sections?
    func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
        return 50
    }

    //How many rows in each section?
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return chatMessages[section].count
    }

    //What is in each of these rows?
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cellId", for: indexPath) as! ChatCell
        let chatMessage = chatMessages[indexPath.section][indexPath.row]
        cell.chatMessage = chatMessage
        return cell
    }
}

最佳答案

看起来您正在 chatMessages.append 中添加所有消息,而不是仅添加新的或更改的消息。一种强力解决方案可能是在 sortedKeys 循环之前添加 chatMessages = []

您还可以在消息中添加某种时间戳,然后只添加较新的消息。不确定哪个更有效或更适合您的具体情况 - 您必须自己测试。

关于ios - 如何根据日期(部分)对 UITableView(聊天气泡)中的消息进行分组?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59828134/

相关文章:

swift - 删除填充的 NSBezierPath

uitableview - 更改导航 Controller 中“编辑”按钮的字体

android - 检查您的 google-services 插件配置,未填充 default_web_client_id 字符串

java - 从 Firebase 中嵌套保存的数据中检索数据

Android 模拟器您的设备目前没有健康的互联网连接

ios - 为什么 Xcode 不允许我使用 presentViewController?

iphone - 使用 ASIHTTPRequest 上传 txt 文件

swift - 在 Swift 中访问共享容器中的自定义对象

ios - 将 tableViewCell 中的数据传递给另一个 VC 失败

iOS Dev - 如何检测用户通过按 "Back"访问此 UIViewController