ios - 从 firebase 获取用户消息

标签 ios swift firebase firebase-realtime-database

当用户进行对话时,我希望对话显示在 tableViewController 中。例如,如果 User1 向 User2 发送 10 条消息,那么我的 TableView 中应该有一个单元格显示 User1 - User2 对话中发送的最后一条消息。同样,如果 User1 向 User3 发送 4 条消息,则 User1 应该有两个 tableView 单元格,而 User2 和 User3 应该只有 1 条消息。 我的数据库如下所示:

messages
      hx1DXeMFRU
         -KkVUFuhv7xsYVhnjldV
              ReceiverId: "hx1DX1hW5JZMSmDjwQRUYo3i5Yt2"
              senderId: "eMFRUhfmckTq9cRWNnwIc9mqxxv1"
              text:"hey"
              convoId: hx1DXeMFRU
              timestamp: 1495193736.860723
          -KkVUJG8VPOijCvzMKRf
              ReceiverId: "eMFRUhfmckTq9cRWNnwIc9mqxxv1"
              senderId: "hx1DX1hW5JZMSmDjwQRUYo3i5Yt2"
              text:"Hey how are you?"
              convoId: hx1DXeMFRU
              timestamp: 1495193699.448048

我正在使用下面的函数来检索所有消息并在 messagesViewController 中查看它们。但是,当我尝试附加两个唯一用户之间的对话时,它会将所有消息附加到一个单元格中。因此,在我的具体示例中,我应该有两个单元格,一个用于 User1 与 User2 通信,一个用于 User1 与 User3 通信。

import UIKit
import Firebase
import FirebaseStorage
import FirebaseAuth
import FBSDKCoreKit
import FBSDKLoginKit
import FirebaseDatabase
import JSQMessagesViewController


class MessagesTableViewController: UITableViewController {

    var databaseRef = FIRDatabase.database().reference()
    var loggedInUser = FIRAuth.auth()?.currentUser
    var loggedInUserUid = FIRAuth.auth()?.currentUser?.uid
    var dictDetails: [String:AnyObject]?
    var messages = NSMutableArray()
    var messagesArray = [String]()
    var convoId: String?
    var receiverData: AnyObject?
    let storage = FIRStorage.storage()

    var senderId = FIRAuth.auth()?.currentUser?.uid

    @IBOutlet var MessageTableView: UITableView!

    override func viewDidLoad() {
        super.viewDidLoad()

        self.navigationController?.navigationBar.barTintColor = UIColor(red:0.23, green:0.73, blue:1.00, alpha:1.0)
        self.navigationController?.navigationBar.titleTextAttributes = [NSForegroundColorAttributeName: UIColor.white]

        self.navigationItem.title = "Messages"
        self.navigationItem.rightBarButtonItem?.tintColor = UIColor.white
        self.navigationItem.leftBarButtonItem?.tintColor = UIColor.white


        loadData()

    }


    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


    func loadData()
    {
        let uidToFind = loggedInUserUid as String!
        FIRDatabase.database().reference().child("messages")
            .queryOrdered(byChild: "ReceiverId")
            .queryEqual(toValue: uidToFind).queryLimited(toLast: 1)
            .observe(.childAdded, with: { snapshot in

                let msgDict = snapshot.value as! [String: Any]
                let msg = msgDict["ReceiverId"] as! String
                self.messages = []
                self.messages.append(msg)
                self.MessageTableView.reloadData()
            })
    }

      // MARK: - Table view data source

     override func numberOfSections(in tableView: UITableView) -> Int {
        // #warning Incomplete implementation, return the number of sections
        return 1
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        if messages.count > 0 {
            tableView.backgroundView = .none;
            tableView.separatorStyle  = .singleLine
            return self.messages.count
        }
        else{
            let noDataLabel: UILabel     = UILabel(frame: CGRect(x: 0, y: 0, width: tableView.bounds.size.width, height: tableView.bounds.size.height))
            noDataLabel.text          = "No Messages"
            noDataLabel.textColor     = UIColor.lightGray
            noDataLabel.textAlignment = .center
            tableView.backgroundView  = noDataLabel
            tableView.separatorStyle  = .none
            return 0
        }
    }
    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


      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 {

                                }})}
                                          self.messages.add(value)
                    }}}})}

        return cell
    }
}

最佳答案

问题中代码的问题是这样的

queryEqual(toValue: "senderId")

该查询将查询值为“senderId”(字面意思是字符串 senderId)的 messages/ReceiverId 节点。它需要查询实际的 uid。

func loadData()
{
   let uidToFind = "hx1DX1hW5JZMSmDjwQRUYo3i5Yt2"
   FIRDatabase.database().reference().child("messages")
                         .queryOrdered(byChild: "ReceiverId")
                         .queryEqual(toValue: uidToFind)
                         .observe(.childAdded, with: { snapshot in

      let msgDict = snapshot.value as! [String: Any]
      let msg = msgDict["ReceiverId"] as! String
      self.messages = []
      self.messages.append(msg)
      self.MessageTableView.reloadData()
   })
}

我要强调的是,虽然这段代码有效,但它会迭代所有与 ReceiverId = uid 匹配的子节点,一次加载一个,并为之后添加的任何新子节点留下一个观察者。

这是一件好事,因为它允许您使用多个值填充数组以及附加新值的监听器。

但是,如果您确实只对最近的帖子感兴趣,更好的方向是使用 queryLimitedToLast(1) ,它只会返回与查询匹配的最后一个节点。

类似于

var messages = [String]()
func loadData()
{
   let uidToFind = "hx1DX1hW5JZMSmDjwQRUYo3i5Yt2"
   FIRDatabase.database().reference().child("messages")
                         .queryOrdered(byChild: "ReceiverId")
                         .queryEqual(toValue: uidToFind)
                         .queryLimited(toLast: 1)
                         .observe(.childAdded, with: { snapshot in

      let msgDict = snapshot.value as! [String: Any]
      let msg = msgDict["ReceiverId"] as! String
      self.messages = []
      self.messages.append(msg)
      //self.MessageTableView.reloadData()
      print(self.messages) //this will print the last msg and any new msgs
   })
}

关于ios - 从 firebase 获取用户消息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44093069/

相关文章:

ios - 我的 iOS 开发者证书或私钥在 git 中吗?

ios - 为什么我们不能在swiftUI预览中传递实例变量?

android - 我想使用 Firebase 提供的服务器时间戳设置计算优先级

Android Facebook 使用新的 Firebase 登录 : App gets redirected to the login screen even after allowing permission

ios - 将 UITableView Cell 滚动到表格边界之外

ios - Admob 导致 Cocos2d 触摸延迟

iOS Swift 和计时器

javascript - 使用 React 和 firereact 从 Firebase 中删除节点

ios - 使用 BGTaskScheduler 进行后台获取可以完美地与调试模拟配合使用,但在实践中却无法使用

ios - 根据单击的单元格更改变量