Variable username is not updated after call to Firebase - ios

var username: String? = nil
self.ref.child("users").observeSingleEvent(of: .value, with: { (snapshot) in
let usersProfile = snapshot.value as? NSDictionary
let userProfile = usersProfile![userID] as? NSDictionary
username = userProfile!["username"] as! String
}) { (error) in
print(error.localizedDescription)
}
print(username)
Why is the variable username not updated in the end?

You can try like this
var username: String? = nil
self.ref.child("users").observeSingleEvent(of: .value, with: { (snapshot) in
if let usersProfile = snapshot.value as? NSDictionary, let userProfile = usersProfile![userID] as? NSDictionary, let name = userProfile!["username"] as? String {
username = name
}
}) { (error) in
print(error.localizedDescription)
}
print(username)

Related

Using value(forKey: String) gives an error

I am trying to retrieve data from Firebase but I've run into a problem and I can't seem to solve it. Here is my code:
Database.database().reference().child("Users").child(userID!).observeSingleEvent(of: .value) { (snapshot) in
if let name = snapshot.value(forKey: "name") as? String {
userName = name
print(userName)
}
if let username = snapshot.value(forKey: "Username") as? String {
userUsername = username
print(userUsername)
}
if let email = snapshot.value(forKey: "Email") as? String {
userEmail = email
print(userEmail)
}
}
Running this gives me an error:
'NSUnknownKeyException', reason: '[
valueForUndefinedKey:]: this class is not key value coding-compliant
for the key Username.'
Here is a picture of my database:
First Convert snapshot value to Dictionary and then get value from it like below
Database.database().reference().child("Users").child(userID!).observeSingleEvent(of: .value) { (snapshot) in
if let data = snapshot.value as? [String: String] {
let name = data["name"]!
let email = data["email"]!
let userName = data["Username"]!
}
You need to cast snapshot.value which of type Any to [String:String]
Database.database().reference().child("Users").child(userID!).observeSingleEvent(of: .value) { (snapshot) in
guard let res = snapshot.value as? [String:String] else { return }
if let name = res["name"] {
userName = name
print(userName)
}
if let username = res["Username"] {
userUsername = username
print(userUsername)
}
if let email = res["Email"] {
userEmail = email
print(userEmail)
}
}

How to use the variable of FirebaseReference.observeSingleEvent into another function

I want to use variable_a in another function. Actually, I want to load these data into tableviewcell.
func readFIRData() {
var credentials:[String]
let userID = Auth.auth().currentUser?.uid
ref = Database.database().reference().child("usr").child(userID!)
ref.observeSingleEvent(of: .value, with: { (snapshot) in
// Get user value
let value = snapshot.value as? NSDictionary
let Name = value?["firstName"] as? String ?? ""
let PhoneNo = value?["mobile"] as? String ?? ""
var variable_a = [Name,PhoneNo]
self.tableView.reloadData()
}) { (error) in
}
}
You should have a callback (completion handler) in your readFIRData function, and pass variable_a as a parameter in that callback. Parse it into object which you use in table view, and reload tableView in the callback.
Function should look like this:
func readFIRData(_ completion: ([Name,PhoneNo]) -> ()) {
var credentials:[String]
let userID = Auth.auth().currentUser?.uid
ref = Database.database().reference().child("usr").child(userID!)
ref.observeSingleEvent(of: .value, with: { (snapshot) in
// Get user value
let value = snapshot.value as? NSDictionary
let Name = value?["firstName"] as? String ?? ""
let PhoneNo = value?["mobile"] as? String ?? ""
var variable_a = [Name,PhoneNo]
completion(variable_a)
}) { (error) in
}
}
and then have another function which is going to call readFIRData function:
func requestData() {
readFIRData() { [weak self] data in
guard let `self` = self else { return }
self.data = data
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
}
Mention how you get back to main thread to reload tableView. By self.data I assumed data which you will use in table view to instantiate cells.
Solved this way
func GetData(completion: #escaping(_ credentials: [String]) -> Void) {
let userID = Auth.auth().currentUser?.uid
ref = Database.database().reference().child("usr").child(userID!)
ref.observeSingleEvent(of: .value, with: { (snapshot) in
let value = snapshot.value as? NSDictionary
let Name = value?["firstName"] as? String ?? ""
let PhoneNo = value?["mobile"] as? String ?? ""
var variable_a = [Name,PhoneNo]
completion(variable_a)
self.tableView.reloadData()
}) { (error) in
}
}
Now, assign StringArray to some variable. Use below code to assign. Likewise variable StringArrayVariable can be used to populate tableview cells.
GetData { (StringArray) in
self.StringArrayVariable= StringArray
}

retrieve current user data from the firebase

let userId = Auth.auth().currentUser?.uid
Database.database().reference().child("Employess").child(userId!).observeSingleEvent(of: .value, with: { (snapshot) in
// Get user value
let value = snapshot.value as? NSDictionary
//print(value)
let Name = value?["name"] as? String
print(Name)
// ...
}) { (error) in
print(error.localizedDescription)
}

IndexPath in cells after atomic update

I have this function that it will be triggered every time a user changes his picture, and will get the profilePictureUrl of the current user and update all posts matching the currentUser in the database. Works fine! Is doing the job. How do I update the indexPath of those particular cells? Right now my cells images are empty after the update.
var pathToPictures = [Pictures]()
func updateAllImagesOfCurrentUserInDatabase() {
//refrences
let ref = FIRDatabase.database().reference()
let uid = FIRAuth.auth()?.currentUser?.uid
//match the user ID value stored into posts with current userID and get all the posts of the user
let update = ref.child("posts").queryOrdered(byChild: "userID").queryEqual(toValue: uid)
update.observe(FIRDataEventType.value, with: { (snapshot) in
self.pathToPictures.removeAll()
if snapshot.value as? [String : AnyObject] != nil {
let results = snapshot.value as! [String : AnyObject]
for (_, value) in results {
let pathToPostPicture = Pictures()
if let pathToImage = value["pathToImage"] as? String , let postID = value["postID"] as? String {
pathToPostPicture.postImageUrl = pathToImage
pathToPostPicture.postID = postID
self.pathToPictures.append(pathToPostPicture)
print("Image and POST ID: \(pathToPostPicture.postImageUrl!)")
print("Post ID is : \(postID)")
if FIRAuth.auth()?.currentUser?.uid == uid {
ref.child("Users_Details").child(uid!).child("profileImageUrl").observeSingleEvent(of: .value, with: { (userSnapshot) in
print(userSnapshot)
let userIMageUrl = userSnapshot.value as! String
pathToPostPicture.postImageUrl = userIMageUrl
self.pathToPictures.append(pathToPostPicture)
print("This is the image path:" + userIMageUrl + String(self.pathToPictures.count))
// Update the Database
let postIDCount = pathToPostPicture.postID!
let updatedUserData = ["posts/\(postIDCount)/pathToImage": pathToPostPicture.postImageUrl!]
print("This is THE DATA:" , updatedUserData)
ref.updateChildValues(updatedUserData as Any as! [AnyHashable : Any])
})
}
print(self.pathToPictures.count)
}
}
} else {
print("snapshot is nill - add some data")
}
self.collectionView?.reloadData()
})
}

Firebase NSNull Exception while taking Snapshot of Data

i was making a Firebase practice app and i encountered this problem. Where i got NSNull exception while capturing a value from Firebase database. Here is the code
user = FIRAuth.auth()?.currentUser
ref = FIRDatabase.database().reference()
let userid = user.uid
if userid != nil
{
print("User Nid \(userid)")
ref.child("users").child(userid).observe(.value, with: {
(snapshot) in
if(snapshot.exists()){
var user_details = snapshot.childSnapshot(forPath: "\(userid)")
var user_det = user_details.value as! Dictionary<String, String>
print("User Name \(user_det["name"])")
}
else{
print("Does not exist")
}
})
}
and here is the database.
uid
user-details
name: "Salman"
propic: "picurl"
Could you try with this way
ref.child("users").child(userID!).observeSingleEvent(of: .value, with: { (snapshot) in
// Get user value
let value = snapshot.value as? NSDictionary
if let userDetail= value?["user-details"] as? [String:Any] {
// let username = value?["name"] as? String ?? ""
let username = userDetail["name"] as? String ?? ""
}
}) { (error) in
print(error.localizedDescription)
}

Resources