从firebase获取用户消息

时间:2017-05-21 04:07:17

标签: 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
    }
}

1 个答案:

答案 0 :(得分:0)

问题中代码的问题是这个

queryEqual(toValue: "senderId")

该查询将查询值为" senderId"的消息/ ReceiverId节点。 (字面意思是字符串senderId)。它需要查询实际的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
   })
}