当用户进行对话时,我希望对话显示在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
}
}
答案 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
})
}