2

I am doing a chat messenger currently and I am able to retrieve all the messages I sent to another user but not able to retrieve whatever they sent. The codes i used to load my messages is

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()}
    }
}

as for my firebase database, it looks like enter image description here

and the json file of

{
  "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"
    }
  }
}

and my tableviewCells has a config function of

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
    }
}

how should i attempt as to be able to show both what my recipient sent to me and what I have sent to them in my chat logs?

William Loke
  • 377
  • 1
  • 4
  • 25

3 Answers3

2

Typically in chat apps, I model the data as "chat rooms". So if there is a chat between two individuals, I create a node for that conversation.

This looks really similar to your data structure, but now with a single node for the "room". When possible I like to base the room id on the UIDs of the participants (for more on this see http://stackoverflow.com/questions/33540479/best-way-to-manage-chat-channels-in-firebase). So in your case:

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

With this structure, you can easily show the entire conversation between the two users by looking up their room and then simply listing the messages.

For the "list of conversations" for a user, I then model an additional node for each user:

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

In here you can keep whatever information you need to display the list of conversations, such as the "room name" (only commonly used for rooms with >2 participants) or the timestamp of the latest message (useful for showing the conversations in chronological order).

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • so your meaning would be to make it like a room, and put all my messageID under the same room, then load all the messages from the room and sort them by timestamps? – William Loke May 03 '18 at 04:00
  • The push IDs you use are already sorted by timestamp, but... yeah... that's the gist. – Frank van Puffelen May 03 '18 at 04:01
  • sorry am new, i dont understand, Do u have any examples or reference i can see? because if i were to create a new node as "room" on top of my "fromID"-"toID"-"messageID"-.... it seems to not make any changes as it is now? – William Loke May 03 '18 at 04:05
  • Note that I removed the two nested user levels from your structure and replaced them with a single level. So it's: `/rooms/$roomId` and then the messages. It may be a bit harder to read, because I had to type the IDs from your screenshot. If you replace the picture with the actual JSON (which you can can get by clicking the "Export JSON" link in your [Firebase Database console](https://console.firebase.google.com/project/_/database/data)), I'll update my answer to match the exact keys (which hopefully makes it easier to parse). – Frank van Puffelen May 03 '18 at 04:11
2

Actually your node is wrong here .child(fromId).child(toId) this way you can fetch only one side messages.

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

And then store all the messages here and when need to fetch make the chatRoomId in same way. This way you can easily fetch all the chat b/w these two users. I have also answered for paging. So have a look at Firabase Paging and load messages in chunks. It will make the better user experience.

TheTiger
  • 13,264
  • 3
  • 57
  • 82
  • ok, but if this is the way, how would the app know which one to fetch?as in, there are many nodes under chatRoomId – William Loke May 03 '18 at 06:40
  • 1
    `NodeId` should be `chatRoomId` now don't use auto generated key. Other way is to store this `chatRoomId` in every message and use `isEqualTo` query to fetch the messages. – TheTiger May 03 '18 at 06:50
  • just a simple question, the messageID i will still use yea? it's an id generated by autoID. after the chatRoomId, it's messageID and then the msg contents – William Loke May 03 '18 at 07:01
  • Yes correct, `messageID` (auto generated) is fine. `chatRoomId -> messageId -> messageContent, messageId -> messageContent`. – TheTiger May 03 '18 at 07:07
  • it worked! If i could double upvote you, would do it now..lol..THX! – William Loke May 03 '18 at 07:08
  • 1
    I'm happy for you! (y) – TheTiger May 03 '18 at 07:13
0

Can you try saving toId and fromId as Strings?

let toId = String(user!.id!)

This worked for me once.