Update Value Firebase Swift 3 - ios

I'm having trouble updating a value in my Firebase database with the key status. I just can't figure out how to access the child(id) in which it is an autoID. Should I have an attribute in my Swift 3 Entity? Or is there a child(autoID) or something similar? I'm new in Firebase and Swift 3. Can any one help? This is my code:
self.ref?.child("requests").queryOrdered(byChild: "Sender").queryEqual(toValue: self.items[indexPath.row].Sender).setValue("2", forKey: "status"))

Swift 3 && Firebase 3
Hope this code will be help you...
// create the reference you want to observe
let myRequestRef = FIRDatabase.database().reference().child("requests").queryOrdered(byChild: "Sender").queryEqual(toValue: self.items[indexPath.row].Sender)
// check the sender value
myRequestRef.observeSingleEvent(of: .value, with: { (snapshot) in
//get the sender key
let senderKey = snapshot.key as String
// create status ref for new status value
let statusRef = FIRDatabase.database().reference().child("requests").child(senderKey)
// create new dict for status value
let newValue = ["Status": 2] as [String: Any]
statusRef.updateChildValues(newValue, withCompletionBlock: { (error, _) in
if error != nil {
print(error?.localizedDescription ?? "Failed to set status value")
}
print("Successfully set status value")
// Update your UI
DispatchQueue.main.async {
// Do anything with your UI
}
})
}) { (error) in
print("Failed to get snapshot", error)
}

Try moving your code inside .observe. This will allow you to get the status and check that it's accessing the right child. By using the child path below, it will override the status value but not the rest of the values inside the child.
self.ref?.child("requests").queryOrdered(byChild: "Sender").queryEqual(toValue: self.items[indexPath.row].Sender).observe(.value, with: { (snapshot) in
let value = snapshot.value as? NSDictionary
if value != nil {
print(value)
print(value["status"])
// If status is what you want, and prints out the correct status and
// correct child item
// Update the status
self.ref.child("requests/\(self.items[indexPath.row].Sender)/status").setValue("2")
}
})
I haven't tested the code above, but you should be able to make minor tweaks to get it to work in your code and on your firebase database.

You can update status value as below:
self.ref?.child("requests").queryOrdered(byChild: "Sender").queryEqual(toValue: self.items[indexPath.row].Sender).observe(.value, with: { (snapshot) in
let value = snapshot.value as? NSDictionary
if value != nil {
self.ref.child("requests/(self.items[indexPath.row].Sender)").updateChildValues(["status":"2"])
}
})

Related

How do you make a function that has to do a query on the firebase database and return the value of the query as an int?

We are currently making an iOS app and with firebase as its database. Please find below our code.
static func getTilesPerRow () -> Int{
let user = Auth.auth().currentUser
guard let uid = user?.uid else {
return -2
}
var ref: DatabaseReference!
ref = Database.database().reference()
let userRef = ref.child("user").child(uid)
var num = -1
let queue = DispatchQueue(label: "observer")
userRef.child("tilesPerRow").observe(DataEventType.value, with: { (snapshot) in
// Get user value
print("now inside the observe thing------------------")
let value = snapshot.value as? NSDictionary
num = snapshot.value as? Int ?? 0
print("just updated the number to ", num)
print("the snapshot is ", snapshot)
print("the value is ", value)
print("the real value is", snapshot.value)
print("just making sure, the number that was set is ", num)
}) { (error) in
print("there was an error!!!!!!!!!!!!!!!!!")
print(error.localizedDescription)
}
print("about to return from the function ", num)
return num
}
Currently while running this code, we get the following output.
about to return from the function -1
now inside the observe thing------------------
just updated the number to 5
the snapshot is Snap (tilesPerRow) 5
the value is nil
the real value is Optional(5)
just making sure, the number that was set is 5
Our expected output is:
now inside the observe thing------------------
just updated the number to 5
the snapshot is Snap (tilesPerRow) 5
the value is nil
the real value is Optional(5)
just making sure, the number that was set is 5
about to return from the function 5
The problem here is that we are trying to grab the value of what the query has found, but because .observe() is asynchronous, the function finishes before .observe() updates the value of num. How do we return the correct value?
You don't.
To get the asynchronous operation result you use blocks.
static func getTilesPerRow (#escaping completion: (Int?)->Void ) {
let user = Auth.auth().currentUser
guard let uid = user?.uid else {
completion(nil)
}
var ref: DatabaseReference!
ref = Database.database().reference()
let userRef = ref.child("user").child(uid)
userRef.child("tilesPerRow").observeSingleEvent(DataEventType.value, with: { (snapshot) in
// Get user value
print("now inside the observe thing------------------")
let value = snapshot.value as? NSDictionary
let num = snapshot.value as? Int ?? 0
completion(num)
}) { (error) in
print("there was an error!!!!!!!!!!!!!!!!!")
print(error.localizedDescription)
completion(nil)
}
}
When the results are ready you will get notified through the block. Upon success you get the actual num you are looking for or nil upon any error occurred.
Even you can distinguish that what sort of error occurred by adding extra parameter on your parameter list in completion block.
You also could use protocol, but thats require more knowledge like, in which class this code reside, who is the caller this sort of things. Set the protocol target to the caller, and upon completion called method will fire different protocol method based on the error or successful case occurred.
Happy coding.

My firebase int returns nil

I'm trying to pull an int from my firebase db however when I try and set my variable it returns nil.
ref = Database.database().reference()
let UserUID = Auth.auth().currentUser?.uid as? String
ref.child("users").child(UserUID!).child("MaxVal").observeSingleEvent(of:
.value, with: { (snapshot) in
let snap = snapshot.value as? Int
self.MaxValFB = snap! //this returns nil
}) { (error) in
print(error.localizedDescription)
}
Any help apreiciated!
EDIT: upon printing its result it returns
Optional( null)
also here is the db json file
{
"users" : {
"Optional(\"njcfCQaIIhZS9qrqM9OFLqTS7yA2\")" : {
"MaxVal" : 1
}
}
}
I think the problem is this "Optional(\"njcfCQaIIhZS9qrqM9OFLqTS7yA2\")" , when you are saving the data to firebase , you are giving it the id without unwrapping the optional and when you get the value you are unwrapping it like UserUID! , so it gives "njcfCQaIIhZS9qrqM9OFLqTS7yA2" , hence these are two different values.
So I think you should unwrap the userid when you save the data to firebase or try to get it without unwrapping i.e child(UserUID) without ! , although I would suggest to go with the first option.

Firebase get child name by value and remove it

My JSON looks like this:
users
username1: "WWOdh96Yr3Qs4N3GWDVq3OlQFfB2"
username2: "RJ6PztTLmsg222oUygWHtWpVHdg1"
I would like to get "username1" by their key which is (auth.uid)! and if its found i want to delete it, So after delete it will be looks like this:
users
username2: "RJ6PztTLmsg222oUygWHtWpVHdg1"
.
self.ref.child("users").queryOrderedByValue().queryEqual(toValue: user?.uid).observe(.value, with: { snapshot in
if snapshot.exists() {
print("\(snapshot.value)")
snapshot.ref.child(snapshot.value as! String).removeValue() // this deleting every thing which is WRONG!
} else{
print("Not found--")
}
self.ref.removeAllObservers()
})
}
This code deleting everything in users. I just want to delete specific user.
First of all, my approach is if I want to query 1 value at 1 moment, like you are doing, I do a observeSingleEvent (is this the best approach?). But to solve your problem, you forgot to add your "users" path. Below code is more safe to use, since you force unwrap (which is not recommend for this case):
let dataRef = self.ref.child("users")
dataRef.keepSynced(true)
if let usersUID = Auth.auth().currentUser?.uid{
dataRef.child("users").queryOrderedByValue().queryEqual(toValue: usersUID).observeSingleEvent(.value, with: { snapshot in
print(snapshot)
let values = snapshot.value as? NSDictionary
for (key, value) in values{
print(value) // does this print the uid?
print(key) // or this one?
self.ref.child("users/\(key)").removeValueWithCompletionBlock({ (err, ref) in
if err != nil {
print(err)
} else {
print(ref)
print("Removed")
}
})
}
})
}
Try to add this, right after the print(snapshot)

Popup alert not showing when a match is not found in database

I'm using this function to check to see if a certain handle exists in my database. It works fine for the most part - if the handle exists, it updates the table view to display that user. However if there is no match for the handle entered, my alert view is not showing up.
// Search DB for matching handles
#IBAction func searchHandleButtonPressed(_ sender: Any) {
if let handleToSearch = handleSearchTextField.text?.lowercased() {
let databaseRef = FIRDatabase.database().reference()
databaseRef.child("users").queryOrdered(byChild: "lowercaseHandle").queryEqual(toValue: handleToSearch).observeSingleEvent(of: .value, with: { (snapshot) in
if let snapDict = snapshot.value as? [String:AnyObject] {
for each in snapDict{
let key = each.key
let handle = each.value["handle"] as! String
self.returnedHandles.removeAll()
self.returnedHandles.append(handle)
let pic = each.value["profilePicture"] as! String
self.returnedUsersProfilePic = pic
self.returnedUsersUID = key
if handle.lowercased() != handleToSearch {
self.noHandleFoundAlert()
}
if handle != "" {
DispatchQueue.main.async {
self.getFriendsInfo()
self.tableView.reloadData()
}
}
}
}
}, withCancel: {(Err) in
// print(Err.localizedDescription)
})
}
}
I put the alert in the loop as:
if handle.lowercased() != handleToSearch {
self.noHandleFoundAlert()
}
But obviously this isn't the correct approach as it isn't working. If I enter a random string of characters, or a handle that I know isn't in use, the alert doesn't come up. Where else would I put the alert so it will show up if there's no match?
The snapshot will be converted to an empty dictionary with your current code.
Before converting the snapshot.value to a Dictionary, check if it exists with snapshot.exists(): https://firebase.google.com/docs/reference/ios/firebasedatabase/api/reference/Classes/FIRDataSnapshot#-exists
You first have to check if the query you made, has data. So you have a
.hasChild("handle")
it returns a boolean, so when is true you do the loop, else notified user.

Retrieving data with Firebase database in iOS

In my app I have a simple user base that looks like this:
What I'm trying to do is to simply fetch this list once, to check wether a username is valid when a new user signs up with a new username.
The thing is that the only ways I found to retrieve data utilize some sort of observer methods, which are not good for me.
The logic I'm trying to achieve (with the retrieving method that doesn't work) :
// When user tries to sign up with a new username
let username = nicknameField.text?.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet())
self.usersRef.observeEventType(.Value) { (snapshot: FIRDataSnapshot) in
let dict = snapshot.value as! NSDictionary
for val in dict.allValues {
if username == val as! String {
// Present alert
return
}
}
}
self.usersRef.child(username).setValue(username) { (error, dbRef) in
if error == nil {
// Continue
}
}
How can I simply just fetch the list of users once?
Thanks in advance!
I had to change the observeEventType method to observeSignleEventOfType.
I have also updated my code to make it work (regardless):
self.usersRef.observeSingleEventOfType(.Value) { (snapshot: FIRDataSnapshot) in
let dict = snapshot.value as! NSDictionary
for val in dict.allValues {
if username == val as! String {
// Present alert
return
}
else {
self.usersRef.child(username).setValue(username) { (error, dbRef) in
if error == nil {
// Continue
}
}
}

Resources