我正在寻求用我的用户发送或被发送的最后一条消息来填充他们的表视图,就像iphone上的初始消息视图应用程序一样。我有这段代码,但它无法遍历我保存的所有发送给用户的消息的快照并返回预期结果的字典数组:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! MyTableViewCell
func getMsg()-> Int{
var getIndex = Int()
let messageDb = Database.database().reference().child("iMessenger/Messages")
messageDb.observe(.childAdded) { (snapshot) in
if let snapshotvalue = snapshot.value as? [String:Any], let sender = snapshotvalue["sender"] as? String, let key = snapshotvalue["key"] as? String{
// I thought that I could iterate through my array of dictionaries taking care to find a matching sender value for the user at indexpath.row and the key for the message
for (index, dict) in newMessageDictArr.enumerated(){
if self.users[indexPath.row].userPhone == sender && dict["key"] == key{getIndex = index}}}}
return getIndex}
if newMessageDictArr.count != 0{
cell.userMessage.text = newMessageDictArr[getMsg()]["messageBody"]}
return cell}
我对代码的问题是
cell.userMessage.text = newMessageDictArr[getMsg()]["messageBody"]
使我的所有单元格都具有["messageBody"]的第一个值,所以我的所有用户似乎都向我发送了相同的消息。想弄清楚我哪里错了。。。
这也是我的FireBase结构,谢谢。
{
"iMessenger" : {
"Messages" : {
"-KxDSQOBuCkpFdw4SPDh" : {
"messageBody" : "TEST ",
"receiver" : "+197862",
"sender" : "+16698"
},
"-KxBjNM_iA2XaapyyC9o" : {
"key" : "-KxBjNM_iA2XaapyyC9o",
"messageBody" : "TEST",
"receiver" : "+197862",
"sender" : "+1914862"
},
"Messages+199862+197862" : {
"-KxB7P-vgdfxRpSdnwCT" : {
"messageBody" : "yo, wassup world",
"receiver" : "+197862",
"sender" : "+199862"
},
"-KxB81fbn5_OHxdj4lcA" : {
"messageBody" : "Hello World",
"receiver" : "+19147862",
"sender" : "+1997862"
}
},
"Users" : {
"-Kx41o03NIMBR68F2sCS" : {
"displayName" : "sleeping beauty ",
"firstName" : "",
"lastName" : "",
"phoneNumber" : "+165698"
},
"-Kx42IXgN1z9D5Zoz0fk" : {
"displayName" : "KarmaDeli",
"firstName" : "",
"lastName" : "",
"phoneNumber" : "+1397862"
}}}}
这个问题有点不清楚,但让我试一试:
从概念上讲,tableView由一组数据支持。当数据发生变化时,应该更新数组,然后调用tableView.reloadData来刷新tableView中的内容。一般来说,该技术为用户提供了最流畅的体验。
IMO,应该重写代码以遵循该设计模式。我不会写所有的代码,但会提供一个流程和几个代码片段来给你一些指导。这些没有经过测试,所以不要复制和粘贴。
首先,从两个类开始
class MessageClass {
var msgId = ""
var msgBody = ""
var msgSenderUid = ""
var msgReceiverUid = ""
}
class UserClass {
var uid = ""
var name = ""
func init(aUid: String, aName: String) {
self.uid = aUid
self.name = aName
}
}
然后有两个数组来跟踪数据-第一个是messagesArray,它将是表的dataSource查看
var messagesArray = [MessageClass]()
var usersArray = [UsersClass]()
我们假设该应用程序有几百个用户,所以我们只需要在应用程序启动时加载所有用户数据。请记住,如果添加了新用户,usersArray将自动更新为添加的用户
func viewDidLoad() {
let ref = firebaseRef.child("users")
ref.observe(.childAdded..... { snapshot in
let userDict = snapshot.value as! [String: Any]
let uid = userDict.key
let name = userDict["name"] as! String
let userClass = User(aUid: uid, aName: name)
self.usersArray.append(userClass)
还可以在消息节点中添加一个观察者,这样你的应用程序就会收到新消息的通知。我们将利用Firebase查询观察器,这样该用户将只收到的消息通知
let queryRef = firebaseRef.child("messages")
queryRef.queryOrdered(byChild: "msg_receiver_uid").query(equalTo: thisUsersUid) {
let dict = snapshot.value as! [String: Any]
let sendersUid = dict["msgSenderUid"] as! String
let msgText = dict["msgBody"] as! String
//create a MessageClass object and populate it with data
//add it to the messagesArray
tableView.reloadData()
最后,在tableView函数中,从dataSource messagesArray中获取每一行,并创建和填充每个单元格。
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! MyTableViewCell
let msg = self.messagesArray[indexPath.row]
let msgSenderUid = msg.msgSenderUid
let sendersName = //some function to look up the senders name from the users array
let msg = msg.msgBody
//populate cell with users name and msg body
return cell
同样,这不是为了复制/粘贴,而是为了提供一个示例流程。
当发布新消息时,如果消息是针对该用户的,则会通过查询观察器通知他们该消息,并在事件中显示该消息。消息被填充到一个消息类对象中,添加到数据源数组中,并更新表视图以显示它
其中一个注意事项是,如果您不想加载所有用户。在这种情况下,当消息事件发生时,在users节点上执行observeSingleEvent以检索用户信息。然后在该闭包中,构建messageClass,添加到数组并重新加载tableView。
希望能有所帮助。