附加 Firebase 聊天消息

Posted

技术标签:

【中文标题】附加 Firebase 聊天消息【英文标题】:Append Firebase chat messages 【发布时间】:2017-05-19 12:21:34 【问题描述】:

我正在创建一个聊天应用程序,并且我在表格视图单元格中列出了两个用户之间发送的所有消息。例如,我在两个用户之间总共有四个文本,所以我有四个单元格。但是,我想对单元格进行分组,以便我只有一个单元格,因为我的 loggedInUser 只与一个人交流。无论我做什么,消息都不会附加。

func loadData()
if (FIRAuth.auth()?.currentUser) != nil

FIRDatabase.database().reference().child("messages").observeSingleEvent(of: .value, with:  (snapshot:FIRDataSnapshot) in

let loggedInUserData = snapshot
if let postsDictionary = snapshot .value as? [String: AnyObject] 

for post in postsDictionary 
    let messages = post.value as! [String: AnyObject]
    for (id, value) in messages 
        let info = value as! [String: AnyObject]
        if let receiver = info["ReceiverId"] 
        print("\(id): \(receiver)")
       self.messages.Array(value)

        

    
    self.MessageTableView.reloadData()



)

到目前为止,我的应用正在显示两个用户之间的消息,如下所示:

我认为问题出在self.messages.Array(value) 我只需要在相同的两个用户之间附加消息,但我找不到正确的代码

但我希望两个用户之间的对话在一个单元格中(附加它)

这是我的单元格的样子:

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
    let cell = tableView.dequeueReusableCell(withIdentifier: "MessageCell", for: indexPath) as! MessageTableViewCell


    //Configure the cell


    print(messages[indexPath.row])
    let message = self.messages[indexPath.row] as! [String: AnyObject]
    if let seconds = message["timestamp"] as? Double 
        let timeStampDate = NSDate(timeIntervalSince1970: seconds)
        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = "hh:mm a"
        cell.Time.text = dateFormatter.string(from: timeStampDate as Date)
    



    cell.Message.text = message["text"] as? String
   // cell.SellerName.text = message["ReceiverId"] as? String


  if let imageName =  message["ReceiverId"] as? String 

        let ref = FIRDatabase.database().reference().child("posts").child(imageName)

    ref.observeSingleEvent(of: .value, with:  (snapshot)
        in

        if let dictionary = snapshot.value as? [String: AnyObject]
            for post in dictionary 
                let messages = post.value as! [String: AnyObject]
                for (id, value) in messages 

                cell.SellerName.text = messages["username"] as? String
                    if (messages["uid"] as? String) != nil 
                        let uidPoster = messages["uid"] as? String
                        let imageRef = FIRStorage.storage().reference().child((uidPoster)!+"/profile_pic.jpg")

                        imageRef.data(withMaxSize: 25 * 1024 * 1024, completion:  (data, error) -> Void in
                            if error == nil 

                                let image = UIImage(data: data!)
                                cell.UserPic.image = image

                                cell.UserPic.layer.cornerRadius = 30
                                cell.UserPic.clipsToBounds = true



                            else 

                                print("Error downloading image:" )


                            )

                    self.messages.add(value)
                
            


        

    )
    

    return cell

我的 firebase 消息路径是:

FIRDatabase.database().reference().child("messages").child("(self.convoId!)").childByAutoId()

这是我的数据库结构:

【问题讨论】:

离题但为什么你会观察一个事件而不是添加孩子?这样所有旧邮件和新邮件都会被下载。 @J.Doe 它工作正常。下载新旧消息没有问题 请解释一下。你想当我按顺序发送 4 条消息时,它们应该彼此附加为一个单元格吗? 就像手机中的短信一样,当您给某人发短信时,您的所有聊天都应该在一个单元格中@VladPulichev @juelizabeth 其实我没看懂你的意思:(请加截图,什么意思? 【参考方案1】:

我将在我的回答中使用一个超级简单的例子。

给定一个结构

messages
   msg_0
      rec: "uid_0"
      send: "uid_1"
      msg: "msg from uid_0 to uid_1"
   msg_1
      rec: "uid_1"
      send: "uid_0"
      msg: "msg from uid_1 to uid_0"

向消息节点添加一个查询观察者,以监视任何具有 uid_0 的 rec: 的新消息 (.childAdded)。

var messagesArray = [String]()

func watch() 
    let messagesRef = self.ref.child("messages")
    let queryRef = messagesRef.queryOrdered(byChild: "rec").queryEqual(toValue: "uid_0")

    queryRef.observe(.childAdded, with:  snapshot in

        let msgDict = snapshot.value as! [String: Any]
        let msg = msgDict["msg"] as! String

        self.messagesArray = [] //erases the array
        self.messagesArray.append(msg) //adds this new message at index 0

        print(self.messagesArray) //print is just for example
        //normally call tableView.reloadData() which will refresh
        //  the cells in the tableView and display just once cell with
        //  the latest message in it
    )

您可以通过将快照或字典存储在数组中来推断这一点,这样您就可以了解消息文本并可以使用 send: user id 来查找发送消息的人。

如果您运行此代码,输出将是发送到 uid_0 的任何新消息;只会显示最新消息。如果你有一个带有 messagesArray 的 tableView 作为它的数据源(这通常是它的完成方式),那么 tableView 将被刷新并且只显示 uid_0 的最新消息。

顺便说一句,.queryLimited(toLast:) 可以在这里很好地利用。

【讨论】:

因为很难访问 convoId 节点,所以我不确定在哪里放置 .queryLimited(toLast:) @juelizabeth 你真的不需要在我提供的代码中使用它——我的代码已经过测试、工作并提供了解决方案。即使您确实使用了 .queryLimited,代码也几乎相同。使用我发布的内容并首先使其正常工作,然后如果您想稍后更改它,您将对流程有更好的理解。 (什么是convold?)如果我的解决方案有帮助,请务必接受它,以便它可以帮助其他人!【参考方案2】:

1) 我认为,在您的情况下,您应该 .queryLimited(toLast: 1) 向每个聊天消息发送消息。如果详细信息打开 - 加载其他消息。

2) 但我有一个假设,即您的数据库结构错误。 Check this

在这里,您可以找到 firebase 文档作者的聊天数据库的良好结构。

您还可以查看这个制作聊天应用的旧 sn-ps:Link

希望对你有帮助

【讨论】:

将查询限制为 1 并没有什么不同,我仍然有四个单元格 我认为问题出在self.messages.Array(value) 我只需要在相同的两个用户之间附加消息,但我找不到正确的代码 @juelizabeth 实际上,我认为最好对您的数据库结构进行一些研究。但是等等,我会想 抱歉,我认为您在 .queryLimited(toLast: 1) 上可能是对的,但我没有把它放在正确的位置。我应该把它放在哪里

以上是关于附加 Firebase 聊天消息的主要内容,如果未能解决你的问题,请参考以下文章

输入聊天消息时的Firebase警告[重复]

是否有必要在将聊天消息存储到 Firebase 之前对其进行加密?

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

使用 Firebase 的聊天应用程序:收到新消息时获取通知 - Android

使用 firebase 按最新消息对聊天列表进行排序

聊天应用程序的 Firebase 推送通知