【问题标题】:Firebase Realtime database - tableview update all the cell data if new data addedFirebase 实时数据库 - 如果添加了新数据,tableview 会更新所有单元格数据
【发布时间】:2021-10-25 15:49:11
【问题描述】:

我正在开发一个群聊应用程序,并尝试从节点获取最后一条消息,以在群组名称下显示最后一条消息。一切正常。当该组收到一条新消息时,最后一条消息会显示在正确的组和其他一些随机组中。如果我打开正确的组并返回,所有其他组都显示正确的最后一条消息。请帮助我使用以下代码。

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return groupList.count
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell:GroupsTableViewCell = tableView.dequeueReusableCell(withIdentifier: "GroupsTableViewCell") as! GroupsTableViewCell
    cell.selectionStyle = .none
    var user: Groupslist
    if groupList.count > 0 {
        user = groupList[indexPath.row]

        cell.lbl_name_group.text = user.name;
        cell.view_count.isHidden = true

        GetLastMsg(groupID: user.group_id ?? "", cell: cell)
        cell.img_group.image = UIImage.init(named:"final_grp")
      GetUnReadMsgCount(groupID: user.group_id ?? "", cell: cell)
    }
    return cell
}

groupList 包含从 viewWillAppear 上的 firebase 获取的组列表​​。

func GetLastMsg(groupID  : String, cell : GroupsTableViewCell){
    let userRef2 = rootRef2.child("message").child(groupID).queryLimited(toLast: 1)
    userRef2.observe( .value, with: { snapshot in
        guard let _ = snapshot.value as? [String:AnyObject] else {
            print("Error")
            return
        }
        print("children count: \(snapshot.children.allObjects.count)")

        for snap in snapshot.children.allObjects as! [DataSnapshot] {
            let message = Message()


            let value = snap.value as? [String: Any] ?? [:]
            let text = value["text"] as? String ?? "Name not found"
            let mimType = value["mimType"] as? String
            let name_doc = value["name_doc"] as? String ?? "file.file"
            message.text = text
            message.mimType = mimType
            message.name_doc = name_doc
            message.timestamp_group = (value["timestamp"] as! NSNumber)

            print(value["idSender"] as? String)
            print(message.name_doc)
            var  msg_last = ""
            //    cell.lbl_lastmsg.text = msg_last
            if message.mimType == "image/jpeg" {
                msg_last = "Image"
                cell.img_small_width.constant=28
                cell.img_small.image = UIImage(named: "im")
            }else if message.mimType == "audio/3gpp" {
                msg_last = "Audio"
                cell.img_small_width.constant=28
                cell.img_small.image = UIImage(named: "mi")
            }else if message.mimType == "video/mp4" {
                msg_last = "Video"
                cell.img_small_width.constant=28
                cell.img_small.image = UIImage(named: "vi")
            }else if message.mimType == "application/pdf" {
                let name_docs = message.name_doc!.split{$0 == "."}.map(String.init)
                msg_last = name_docs.last!
                cell.img_small_width.constant=28
                cell.img_small.image = UIImage(named: "doc")
            }else if mimType == nil{
                msg_last = message.text!
                cell.img_small_width.constant=0
            }
              DispatchQueue.main.async {
                cell.lbl_lastmsg.text = msg_last
            }
          }
          }
    })
   }

新方法:

  func GetUnReadMsgCount(groupID : String, cell : GroupsTableViewCell)  {

    rootRef2.child("group_message_unread").child(current_user!).child(groupID).observe(.childAdded, with: { (snapshot) -> Void in
        print(snapshot.childrenCount)
        print(snapshot.children.description)
        if snapshot.childrenCount > 0 {
            DispatchQueue.main.async {
                cell.view_count.isHidden = false
                cell.lbl_count.text = String(snapshot.childrenCount)
              //  self.tbl_groups.reloadRows(at: [IndexPath(row: 3, section: 0)], with: .fade)
//                    self.tbl_groups.reloadData()
            }
        }
    })

}

【问题讨论】:

    标签: ios swift uitableview firebase-realtime-database


    【解决方案1】:

    这是预期的行为。在.observe( .value 侦听器中,快照始终是路径中的完整数据。因此,当您添加子节点时,快照会在 userRef2 处使用整个新数据触发。

    您有两个主要选项可以避免在 UI 中出现重复项:

    1. 有更新时清除所有消息,然后再将数据添加到表中。所以这就是代码中for snap in snapshot.children 之前的内容。这是迄今为止解决重复行问题的最简单方法,但可能会导致您的 UI 出现一些闪烁。

    2. Listen for child events,而不是观察整个值。有了这个,您将获得新子节点的单个 .childAdded 事件,您可以摆脱 for snap in snapshot.children.allObjects 并将单个新子节点添加到表中。

    【讨论】:

    • 非常感谢您抽出宝贵时间。这是在 cellforrow 方法中调用 firebase 函数的正确方法吗?为了测试您的解决方案,我使用了另一种方法来获取新的未读消息的计数,并使用了 .childAdded 但是当我进入聊天组并返回时仍然如果收到新消息,则消息计数会反映在其他组中还。任何想法?我已经更新了我的代码。 @弗兰克
    • 你要重新连接观察者吗?因为在这种情况下,它确实会再次为每个孩子重新触发.childAdded。如果您只想收听新消息,则需要为此更改侦听器。看看这些关于该主题的问题:stackoverflow.com/…
    • 是的,当屏幕消失时,我正在移除观察者。感谢您的链接,但这对我没有帮助。只有当我进入任何聊天组并返回时才会出现问题,如果有新消息出现,最后一条消息出现在多个单元格中。
    猜你喜欢
    • 2021-10-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-07-08
    • 2020-11-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多