我有一个聊天应用程序。一切正常,除了当我试图根据消息的日期将聊天消息分组时。第一次加载 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/