Reputation: 97
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
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
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