Nedim Kurbegović
Nedim Kurbegović

Reputation: 97

Swift 3 and Firebase - Tableview not updating

Swift 3 and Firebase - I have successfully managed to fetch users' usernames and email addresses in tableview cells. However, when a user changes his username on a separate view controller, the tableview is not updating - the old username is still shown. Please have a look at the code below:

 databaseRef.child("users").queryOrdered(byChild: "username").observe(.childAdded, with: { (snapshot) in

        let key = snapshot.key
        let snapshot = snapshot.value as? NSDictionary
        snapshot?.setValue(key, forKey: "uid")

        if(key == self.loggedInUser?.uid)
        {
            // don't add signed in user to array
        }
        else
        {
            var theUser = User()
            theUser.key = key
            theUser.fullname = snapshot?.value(forKey: "fullname") as? String
            theUser.biography = snapshot?.value(forKey: "biography") as? String
            theUser.location = snapshot?.value(forKey: "location") as? String
            theUser.photoURL = snapshot?.value(forKey: "photourl") as? String
            theUser.username = snapshot?.value(forKey: "username") as? String
            self.arrayOfUsers.append(theUser)
            //insert the rows
            self.SearchUsersTableViewController.insertRows(at: [IndexPath(row:self.arrayOfUsers.count-1,section:0)], with: UITableViewRowAnimation.automatic)

                self.tableView.reloadData()

        }
    })

I have tried placing tableview.reloadData() on multiple places without success. I have also tried using:

DispatchQueue.main.async {
  self.tableView.reloadData()
}

without success. I came up with an idea to append the user again when he changes his username. However, I didn't know how to delete the old one. I thought the best solution was to add observe of type childChanged. The problem was that I couldn't find the index of the user who changed his username in users array.

I would be grateful if someone helps me solve the problem.

EDIT:

I have a struct User:

struct User {
    var username: String?
    var photoURL: String?
    var biography: String?
    var fullname: String?
    var location: String?
    var key: String?
}

For .childChanged I have used the code that Priyamal suggested:

databaseRef.observe(.childChanged, with: { snapshot in
        let ID = snapshot.key //this is the firebaseKey
        if let index = self.arrayOfUsers.index(where: {$0.key == ID}) {
            let changedPost = self.arrayOfUsers[index]
            //update the values
                self.tableView.reloadData()
                print("Change!")
        }
    })

However, when I change the username, I never get to the "Change!" output in my console; therefore, the tableview is not changed.

Upvotes: 1

Views: 546

Answers (2)

Nedim Kurbegović
Nedim Kurbegović

Reputation: 97

I have successfully solved the problem. After I got the index, I only needed to update the user at that specific location in the array and refresh that particular row in the table view!

databaseRef.child("users").queryOrdered(byChild: "username").observe(.childChanged, with: { (snapshot) in
        let ID = snapshot.key
        if let index = self.arrayOfUsers.index(where: {$0.key == ID}) {
            let value = snapshot.value as? NSDictionary
            self.arrayOfUsers[index].username = value?["username"] as? String
            let indexPath = IndexPath(item: index, section: 0)
            self.tableView.reloadRows(at: [indexPath], with: .top)
        }
    })

Upvotes: 0

Priyamal
Priyamal

Reputation: 2989

i think you need to change the event type from childAdded to childChanged with child changed you will only get the updated value. then you must update the existing element in your array.

let's assume your User Struct looks like this

struct User {
    var keyID : String?
    var name : String?
}

    var userArray = [User]() //this represents the array holding user objects 

this method will get called if an update happens

    databaseRef.observeEventType(.ChildChanged, withBlock: { snapshot in
  let ID = snapshot.key //this is the firebaseKey
  if let index = self. userArray.indexOf({$0.keyID == ID}) {
    let changedPost = self. userArray[index]
    //update the values
    self.tableView.reloadData
   }

to load UserArray at the first place use this method.

databaseRef.child("users").queryOrdered(byChild: "username").observe(.value, with: { (snapshot) in

        let key = snapshot.key
        let snapshot = snapshot.value as? NSDictionary
        snapshot?.setValue(key, forKey: "uid")

        if(key == self.loggedInUser?.uid)
        {
            print("Should not be shown!")
        }
        else
        {
            self.usersArray.append(snapshot)
            self.SearchUsersTableViewController.insertRows(at: [IndexPath(row:self.usersArray.count-1,section:0)], with: UITableViewRowAnimation.automatic)

                self.tableView.reloadData()

        }
    })

Upvotes: 1

Related Questions