从 firebase Swift 加载聊天

Posted

技术标签:

【中文标题】从 firebase Swift 加载聊天【英文标题】:loading chats from firebase Swift 【发布时间】:2018-05-03 03:46:45 【问题描述】:

我目前正在做一个聊天信使,我能够检索我发送给另一个用户的所有消息,但无法检索他们发送的任何内容。我用来加载消息的代码是

func loadMsg() 
    let toId = user!.id!
    let fromId = Auth.auth().currentUser!.uid
    let ref = Database.database().reference().child("privateMessages").child(fromId).child(toId)
    ref.observe(.value)  (snapshot) in

        if let snapshot = snapshot.children.allObjects as? [DataSnapshot] 

            self.messages.removeAll()

            for data in snapshot 

                let newMsg = Message(dictionary: data.value as! [String: AnyObject])

                self.messages.append(newMsg)

            
        
        DispatchQueue.main.async self.tableView.reloadData()
    

至于我的 firebase 数据库,它看起来像

以及

的json文件

  "privateMessages" : 
    "0YfqnPIOYFYKb8cYZMHnSYti62i2" : 
      "StHPXFvTlVf5QDvWiuCi4JF8Hyr2" : 
    "-LB0AZRcWF0Ub5ZECzTf" : 
      "fromId" : "0YfqnPIOYFYKb8cYZMHnSYti62i2",
      "textMessages" : "Hi!first msg!",
      "timestamp" : 1524733200,
      "toId" : "StHPXFvTlVf5QDvWiuCi4JF8Hyr2"
    
  ,
  "kj7vcszbSvPBTVaC32Xg18aYZPi1" : 
    "-LB0EpR86dZSYl5p0k-E" : 
      "fromId" : "0YfqnPIOYFYKb8cYZMHnSYti62i2",
      "textMessages" : "Different guy,message 2",
      "timestamp" : 1524734318,
      "toId" : "kj7vcszbSvPBTVaC32Xg18aYZPi1"
    
  
,
"2wYq9dCKF4aZ26nOY41ApPOdGrJ2" : 
  "0YfqnPIOYFYKb8cYZMHnSYti62i2" : 
    "-LBV5jlvtxbZZJFQOwes" : 
      "fromId" : "2wYq9dCKF4aZ26nOY41ApPOdGrJ2",
      "textMessages" : "hi",
      "timestamp" : 1525252029,
      "toId" : "0YfqnPIOYFYKb8cYZMHnSYti62i2"
    
  ,
  "StHPXFvTlVf5QDvWiuCi4JF8Hyr2" : 
    "-LBVCQ5GaEugMNFMT2c-" : 
      "fromId" : "2wYq9dCKF4aZ26nOY41ApPOdGrJ2",
      "textMessages" : "hi",
      "timestamp" : 1525253780,
      "toId" : "StHPXFvTlVf5QDvWiuCi4JF8Hyr2"
    
  
,
"StHPXFvTlVf5QDvWiuCi4JF8Hyr2" : 
  "0YfqnPIOYFYKb8cYZMHnSYti62i2" : 
    "-LBVGEFG76z6tXtq43k5" : 
      "fromId" : "StHPXFvTlVf5QDvWiuCi4JF8Hyr2",
      "textMessages" : "Hi",
      "timestamp" : 1525254780,
      "toId" : "0YfqnPIOYFYKb8cYZMHnSYti62i2"
    
  

  ,
  "users" : 
"0YfqnPIOYFYKb8cYZMHnSYti62i2" : 
  "email" : "test@yahoo.com",
  "id" : "0YfqnPIOYFYKb8cYZMHnSYti62i2",
  "name" : "tester",
  "profileImageUrl" : "https://firebasestorage.googleapis.com/v0/b/groupchatnappointment.appspot.com/o/profile_images%2FE509EFCB-E41D-4E6C-922B-01B146FD1FDC.png?alt=media&token=a7acb904-474b-4898-b99a-1e819ec96afc"
,
"StHPXFvTlVf5QDvWiuCi4JF8Hyr2" : 
  "email" : "test2@yahoo.com",
  "id" : "StHPXFvTlVf5QDvWiuCi4JF8Hyr2",
  "name" : "tester2",
  "profileImageUrl" : "https://firebasestorage.googleapis.com/v0/b/groupchatnappointment.appspot.com/o/profile_images%2F2A5009D7-51C4-4D95-88DF-DADB38C76E7B.png?alt=media&token=ae599135-8ff7-4c64-9667-b9a5cec3dcf8"
,
"kj7vcszbSvPBTVaC32Xg18aYZPi1" : 
  "email" : "tester3@yahoo.com",
  "id" : "kj7vcszbSvPBTVaC32Xg18aYZPi1",
  "name" : "tester3",
  "profileImageUrl" : "https://firebasestorage.googleapis.com/v0/b/groupchatnappointment.appspot.com/o/profile_images%2FD60F2433-14E2-4EE1-AA74-8171CBA1D3AD.png?alt=media&token=728f6171-e48d-4bae-9b84-007937ed3493"
    
  

我的 tableviewCells 有一个配置功能

func configCell(message: Message) 

    self.message = message

    if message.fromId == currentUser 

        sentView.isHidden = false

        sentMsgLabel.text = message.textMessages

        receivedMsgLabel.text = ""

        receivedMsgLabel.isHidden = true

     else 

        sentView.isHidden = true

        sentMsgLabel.text = ""

        receivedMsgLabel.text = message.textMessages

        receivedMsgLabel.isHidden = false
    

我应该如何尝试在聊天记录中同时显示我的收件人发送给我的内容以及我发送给他们的内容?

【问题讨论】:

【参考方案1】:

实际上您的节点在这里.child(fromId).child(toId) 是错误的,这样您只能获取一侧消息。

let chatRoomId = (fromId < toId) ? fromId + "_" + toId : toId + "_" + formId 
/// It will look like "0YfqnPIOYFYKb8cYZMHnSYti62i2_kj7vcszbSvPBTVaC32Xg18aYZPi1"

然后在此处存储所有消息,并在需要获取时以相同的方式制作chatRoomId。这样,您可以轻松地获取这两个用户的所有聊天。我也回答了paging。所以看看Firabase Paging 并以块的形式加载消息。它将带来更好的用户体验。

【讨论】:

好的,但是如果是这样的话,应用程序怎么知道要获取哪一个?例如,chatRoomId下有很多节点 NodeId 应该是 chatRoomId 现在不要使用自动生成的密钥。另一种方法是将此chatRoomId 存储在每条消息中,并使用isEqualTo 查询来获取消息。 只是一个简单的问题,messageID 我还会用吗?它是由 autoID 生成的 id。在chatRoomId之后,是messageID,然后是msg内容 是的,正确,messageID(自动生成)很好。 chatRoomId -&gt; messageId -&gt; messageContent, messageId -&gt; messageContent. 我为你感到高兴! (y)【参考方案2】:

通常在聊天应用程序中,我将数据建模为“聊天室”。因此,如果两个人之间有聊天,我会为该对话创建一个节点。

这看起来与您的数据结构非常相似,但现在“房间”只有一个节点。如果可能的话,我喜欢将房间 ID 建立在参与者的 UID 上(有关更多信息,请参阅http://***.com/questions/33540479/best-way-to-manage-chat-channels-in-firebase)。所以在你的情况下:

privateChats
  0YfqnPIOYFYKb8cYZMHnSYti62i2_StHPXFvTlVf5QDvWiuCi4JF8Hyr2
    -LB0AZ...CzTf
      ...
    -LB0F1...pvyJ
      ...

使用这种结构,您可以通过查找他们的房间然后简单地列出消息来轻松地显示两个用户之间的整个对话。

对于用户的“对话列表”,然后我为每个用户建模一个附加节点:

chatsPerUser
  0YfqnPIOYFYKb8cYZMHnSYti62i2
          0YfqnPIOYFYKb8cYZMHnSYti62i2_StHPXFvTlVf5QDvWiuCi4JF8Hyr2: ...
  StHPXFvTlVf5QDvWiuCi4JF8Hyr2    
          0YfqnPIOYFYKb8cYZMHnSYti62i2_StHPXFvTlVf5QDvWiuCi4JF8Hyr2: ...

在这里,您可以保留显示对话列表所需的任何信息,例如“房间名称”(仅用于有超过 2 个参与者的房间)或最新消息的时间戳(用于显示对话按时间顺序)。

【讨论】:

所以你的意思是把它变成一个房间,把我所有的messageID放在同一个房间下,然后加载房间里的所有消息并按时间戳排序? 您使用的推送 ID 已经按时间戳排序,但是...是的...这就是要点。 对不起,我是新手,我不明白,你有什么例子或参考我可以看到吗?因为如果我要在我的“fromID”-“toID”-“messageID”-....之上创建一个新节点作为“房间”,它似乎没有像现在这样进行任何更改? 请注意,我从您的结构中删除了两个嵌套的用户级别,并将它们替换为单个级别。所以它是:/rooms/$roomId,然后是消息。它可能有点难以阅读,因为我必须从您的屏幕截图中输入 ID。如果您将图片替换为实际的 JSON(您可以通过单击 Firebase Database console 中的“导出 JSON”链接来获取),我将更新我的答案以匹配确切的键(希望这样更容易解析) .【参考方案3】:

您可以尝试将toIdfromId 保存为字符串吗?

let toId = String(user!.id!)

这对我有用一次。

【讨论】:

是的,我有另一个 Message 类文件,我的 toId 和 fromId 设置为“字符串?”。

以上是关于从 firebase Swift 加载聊天的主要内容,如果未能解决你的问题,请参考以下文章

在 Swift 中的 Firebase 实时数据库观察方法中具有异步函数的 DispatchGroup

Swift 3 Firebase 聊天应用程序重复消息

从firebase加载图像并缓存swift3

从 Firebase 中基本读取并使用结果加载 tableview (Swift)

Swift 3:tableView 复制从 Firebase 加载的图像

从 Firebase 检索和读取数据作为 NSArray (Swift 3)