У меня есть приложение чата. Все работает хорошо, за исключением случаев, когда я пытаюсь сгруппировать сообщения чата в разделы, основанные на датах сообщений. При первой загрузке 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 (это делается с помощью функции tryToAssembleGroupMessages )
Если вы, ребята, заинтересованы в поиске при том, как табличное представление извлекает данные, вот код:
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
}
}