Populate TableViewCells with snapShot values in Swift

I’m seeking to populate the tableview of my users with the last message they sent or were sent just like the initial View on Messages App on iphone. I have this code but it doesn’t work to iterate through the array of dictionaries that I keep snapshots in of all the messages that were sent to the user and return the expected result:

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}

The problem I’m having with the code is that

  • Firebase pod install - pod 'Firebase/Database' - Required a higher minimum deployment target
  • Authenticating with Database Secrets in Firebase SDK v3?
  • How to delete from Firebase database
  • Issues implementing AdMob with Firebase iOS
  • Firebase- Could not locate configuration file: 'GoogleService-Info.plist'
  • Use of unresolved identifier FIRDatabase when using Firebase
  • cell.userMessage.text = newMessageDictArr[getMsg()]["messageBody"]
    

    Makes all my cells have the first value for [“messageBody”] so it’s like all my users seemed to have sent me the same message. Trying to figure out where I went wrong…

    Also here’s my FireBase structure, thanks.

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

    Solutions Collect From Internet About “Populate TableViewCells with snapShot values in Swift”

    The question is a bit unclear but let me give it a shot:

    Conceptually, a tableView is backed by an array of data. When that data changes the array should be updated, and then tableView.reloadData should be called to refresh what’s in the tableView. In general, that technique provides the smoothest experience for the user.

    IMO, the code should be rewritten to follow that design pattern. I’m not going to write all the code but will provide a flow and a couple of code snippets to give you some direction. These are not tested so don’t copy and paste.

    First, start with two classes

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

    then two arrays to keep track of data – the first, messagesArray, will be the dataSource for your tableView

    var messagesArray = [MessageClass]()
    var usersArray = [UsersClass]()
    

    We’re going to assume the app has a couple hundred users so we’re just going to load all of the user data in on app start. Keep in mind that if a new user is added, the usersArray will be updated with the additional user automatically

    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)
    

    and also add an observer to the messages node so your app will be notified of new messages. We are going to leverage a Firebase query observer so this user will only be notified of messages meant for them

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

    then finally, in your tableView functions, get each row from the dataSource messagesArray and create and populate each cell.

    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
    

    Again, this is not meant for copy/paste but to provide an example flow.

    As new messages are posted, if the message is for this user, they will be notified of the message via the query observer and presented the message in an event. The messages is stuffed into a message class object, added to the datasource array and the tableview is updated to display it.

    One caveaut to this is if you don’t want to load all of the users. In that case, when a message event occurs, perform a observeSingleEvent on the users node to retreive the user info. Then within that closure, build the messageClass, add to array and reload the tableView.

    Hope that helps.