在 TableView 单元格中处理从 Firebase 检索数据的更好方法



在我的聊天功能中,我在表格视图中向当前用户显示他与其他用户的聊天。表视图上的每个单元格都是相反用户的信息、头像和名称。将这些信息存储在聊天对象中很容易,但问题是对方用户可能已经更改了他的头像或名称。

因此,我在聊天的单元格配置中获取对面用户的头像和名称。它工作正常,但我不确定是否有更好的方法,因为我不相信在每个单元格中进行 Firebase 网络调用。

这是我的单元配置方法:

func configureCell(from chat: Chat){
// 1st Get opposite user id
if let currentUser = Auth.auth().currentUser{
let user1 = chat.people.first
let user2 = chat.people.last
let user1Id = user1?["id"] ?? ""
let user2Id = user2?["id"] ?? ""
var oppositeUserId = ""
if user1Id == currentUser.uid{
oppositeUserId = user2Id
}else{
oppositeUserId = user1Id
}
//2nd Fetch opposite user doc
let oppositeUserDocRef = References.Instance.getUserDocRef(for: oppositeUserId)
oppositeUserDocRef.getDocument { (oppositeUserDocSnapshot, error) in
if error != nil{
print("ERROR FETCHING OPPOSITE USER DOC:: ERROR IS:  (error?.localizedDescription ?? "")")
return
}
// 3rd get opposite user avatar url and name
if let otherUserDic = oppositeUserDocSnapshot?.data(){
if let avatarDic = otherUserDic["avatar"] as? [String: String]{
let avatarUrl = avatarDic["url"] ?? ""
self.avatarView.sd_setImage(with: URL(string: avatarUrl),
placeholderImage: nil, options: .refreshCached)
}
if let name = otherUserDic["name"] as? String{
self.uiLabelChatTitle.text = name
}
}
}
}
}

我从未真正使用过Firebase,但是对于这样的事情,我会说在单个网络请求中填充一个"chatDetails"对象数组,然后配置每个可重用的单元格

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let chat = self.chatDetails[indexPath.row]
let cell = tableView.dequeueReusableCell(withIdentifier: "identifier") as! ChatDetailsCell
cell.configureCell(chat: chat)
return cell
}

正如他们在评论中建议的那样,预取数据将是一个更好的解决方案。这很棘手,取决于每个应用程序的详细信息。我的目标是模仿WhatsApp的聊天列表功能实时更新用户信息。

以下是我为此所做的工作:

func showChats(){
guard let currentUser = Auth.auth().currentUser else{
return
}
let profileController = UserProfileController.instance
if let snapshot = profileController.chats{
for document in snapshot.documents{
let chat = ChatController.instance.getChat(from: document)
chats.append(chat)
print("GOT CHAT:::: (document.data())")
}
tableview.reloadData()
}
else{
print("NOTHING IN INBOX!!!!")
}
// Attach listeners to chat users docs to listen for change in avatars and names
// 1st: Loop through each chat to get people and know opposite user id
for (i, var chat) in chats.enumerated(){
let person1 = chat.people.first
let person2 = chat.people.last
let person1Id = person1?["id"] ?? ""
let person2Id = person2?["id"] ?? ""
var oppositeUserId = ""
var opposteUsrIsPerson1 = false
if person1Id == currentUser.uid{
oppositeUserId = person2Id
opposteUsrIsPerson1 = false
}
else{
oppositeUserId = person1Id
opposteUsrIsPerson1 = true
}
// 2nd: Fetch opposite user doc and add listener to it
let oppositeUserDocRef = References.Instance.getUserDocRef(for: oppositeUserId)
let docListener = oppositeUserDocRef.addSnapshotListener { (oppositeUserDocSnapshot, error) in
if error != nil {
print("ERROR FETCHING OTHER PERSON DOC:: ERROR IS:  (error?.localizedDescription ?? "")")
return
}
// 3rd: get other user avatar url and name from his doc
if let oppositeUserDic = oppositeUserDocSnapshot?.data(){
var avatarUrl = ""
var name = ""
if let avatarDic = oppositeUserDic["avatar"] as? [String: String]{
avatarUrl = avatarDic["url"] ?? ""
}
if let oppositeUsrName = oppositeUserDic["name"] as? String{
name = oppositeUsrName
}
// 4th: Create ChatPerson object with the fetched values and replace the existing one
let chatPerson = ChatPerson(id: oppositeUserId, name: name, avatarUrl: avatarUrl)
if opposteUsrIsPerson1{
chat.people[0] = chatPerson.toDictionalry()
}
else{
chat.people[1] = chatPerson.toDictionalry()
}
// 5th: Update data and reload the chat row
self.chats[i] = chat
let indexpath = IndexPath(row: i, section: 0)
self.tableview.reloadRows(at: [indexpath], with: .automatic)
}
}
//6th: Add doc listener to liteners list to remove it later in deinit()
chatUserListeners.append(docListener)
}
}

在视图控制器的 deinit(( 循环中,遍历侦听器以删除它们:

deinit {
for listener in chatUserListeners{
listener.remove()
}
}

最新更新