问题
I am creating a chat app and I have a list of all the messages sent between two users in a table view cell. For example, I have four texts in total between the two users and so I have four cells. However, I would like to group the cells so that I only have one cell, because I the loggedInUser is only communicating with one person. No matter what I do, the messages will not append.
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()
}
}})}
}
As of now my app is displaying messages between two users like this:
I think the issue is in the self.messages.Array(value) I just need to append messages between the same two users but I can't find the right code
But I would like for a conversation between two users to be in one cell (append it)
This is what my cell looks like:
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
}
my path to firebase message is:
FIRDatabase.database().reference().child("messages").child("(self.convoId!)").childByAutoId()
Here is my database structure:
回答1:
I will use a super simple example in my answer.
Given a structure
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"
Add a query observer to the messages node watching for any new messages (.childAdded) that have a rec: of uid_0.
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
})
}
You can extrapolate from this by storing the snapshot or the dictionary in the array so you know the message text and can use the send: user id to look up who sent the message.
If you run this code, the output will be any new message sent to uid_0; only the latest message will be displayed. If you have a tableView with the messagesArray as it's dataSource (which is normally how its done) then the tableView would be refreshed and only ever show the latest message for uid_0.
As a side note, .queryLimited(toLast:) could be leveraged here was well.
回答2:
1) I think, that in your case you should .queryLimited(toLast: 1) to messages to each chat. And if details opened - load other messages.
2) But I have an assumption, that you have wrong database structure. Check this
Here you can find good structure of the database for chat by firebase doc's authors.
Also you can check this old snippets of making chat app: Link
Hope it helps
来源:https://stackoverflow.com/questions/44070005/append-firebase-chat-messages