Firebase Stuck in infinite loop - ios

I try to change values for all children in Firebase Database. First I try to collect the IDs, and after that, change value.
ref = DatabaseRef.changeUserRef
ref.observe(DataEventType.value, with: { (snapshot) in
if snapshot.childrenCount > 0 {
for items in snapshot.children.allObjects as! [DataSnapshot] {
let itemObject = items.value as? [String: AnyObject]
let id = itemObject?["id"]
self.ref.child(id as! String).child("status").setValue(UserStatus.userOut)
self.ref.child(id as! String).child("inDate").setValue("0000-00-00 00:00")
}
}
})
It works well. All the values are changing as set. But I can't figure out why the app is stuck in this loop. If I try to change any value (like just rewrite in online firebase console), it changes again to UserStatus.userOut's value.
If I close the app, the loop is closed and of course I can change the values.

This
ref.observe(DataEventType.value, with: { (snapshot) in
should be single observe
ref.observeSingleEvent(of: DataEventType.value, with: { (snapshot) in

Related

Fetch first key from firebase database with swift 4 using ChildAdded

I'm trying to fetch the first key from my firebase database but for some reason nothing is being printed out. How can I get the first key from my firebase database using .childAdded
let userMessagesRef = Database.database().reference().child("user-message").child(uid).child(userId)
userMessagesRef.observe(.childAdded, with: { (snapshot) in
guard let first = snapshot.children.allObjects.first as? DataSnapshot else { return }
print(first)
This in incredibly easy if you literally are asking how to only ever get the first child of a node. Here's how to only get the first child of a /users node
func getFirstChild() {
let usersRef = self.ref.child("users")
usersRef.observeSingleEvent(of: .childAdded, with: { snapshot in
print(snapshot)
})
}
or
print(snapshot.key)
if you just want the key.
Or, if you want to use a query to do the same thing
func getFirstChildAgain() {
let usersRef = self.ref.child("users")
let query = usersRef.queryOrderedByKey().queryLimited(toFirst: 1)
query.observeSingleEvent(of: .value, with: { snapshot in
print(snapshot)
})
}
The child_added event is typically used when retrieving a list of items from the database. Unlike value which returns the entire contents of the location, child_added is triggered once for each existing child and then again every time a new child is added to the specified path. The event callback is passed a snapshot containing the new child's data. For ordering purposes, it is also passed a second argument containing the key of the previous child.
From: Read and Write Data on iOS
Per your requirements, this is possible in .value and childAdded.
var child_array = [String:String]
let userMessagesRef = Database.database().reference().child("user-message").child(uid).child(userId)
userMessagesRef.observe(.childAdded, with: { (snapshot) in
let value = snapshot.value as? String ?? "Empty String"
let key = snapshot.key
child_array[key] = value;
}) { (error) in
print(error.localizedDescription)
}
then:
if let first = child_array.first?.key {
print(first) // First Key
}
Big NOTE: child_added randomly collects this data, you should never use it to sort your data

Print All Children Columns from Firebase - iOS Swift 4

I have 2 records in my users table
This code below
let fcmTokenRef = Database.database().reference().root.child("users").child(id!).child("fcmToken")
fcmTokenRef.observe(DataEventType.value, with: { (snapshot) in
print(">>",snapshot)
})
will print out the token of a child
How do I adjust my code to print all the tokens for all my children?
You can try
let fcmTokenRef = Database.database().reference().root.child("users").observe(DataEventType.value, with: { (snapshot) in
print(">>",snapshot)
let dic = snapshot.value as! [String:[String:Any]]
Array(dic.values).forEach {
let str = $0["fcmToken"] as! String
print(str)
}
})
You’re requesting a onetime read, hence you’re reading the data once. You need to use .childAdded
Try this:
let fcmTokenRef = Database.database().reference().child(“users”)
fcmTokenRef.observe(.childAdded, with: { (snapshot) in
print(">>",snapshot)
guard let data = snapshot as? NSDictionary else {return}
var each_token = data[“fcmToken”] as? String
print(“all tokens: \(each_token!)”)
})
#puf says something very important:
differences between child added and value firebase
The child_added event fires for each matching child under the node that you query. If there are no matching children, it will not fire.

Manipulating data after retrieved it from Firebase

Here's my code:
//Get data from Firebase
func getData(withBlock completion:#escaping() ->Void){
let ref = Database.database().reference().child("hobbies")
let query = ref.queryOrdered(byChild: "cost").queryEqual(toValue: "low")
query.observe(.childAdded, with: {(snapshot) in
self.user_choice_Cost.append((snapshot.childSnapshot(forPath: "hobbyName").value as? String)!)
completion()
//print(self.user_choice_Cost)
})
{ (error) in
print(error)
}
//Manipulating data
getData{
let set2:Set<String> = ["a"]
let set1:Set<String> = Set(self.user_choice_Cost)
print(set1.union(set2))}
This works correctly! But is there any way I can get the user_choice_Cost with all value(["a","b"]) instead of one by one(["a"],["a","b")] and manipulate user_choice_Cost array without putting it inside inside getData{}. Because if I put that outside it will return only "a"
When you observe .childAdded, your completion handler gets called for each individual child that matches your query. If you want to get called only once for all matching children, you should observe .value:
query.observe(.value, with: {(snapshot) in
Since your completion handler gets called only once, the snapshot in this case contains all matching nodes. So you need to loop over snapshot.children:
query.observe(.value, with: {(snapshot) in
for child in snapshot.children.allObjects as! [DataSnapshot] {
let value: String = (child.childSnapshot(forPath: "hobbyName").value as? String)!;
user_choice_Cost.append(value)
}
print("value \(user_choice_Cost)")
})
With this code you'll only see one logging output, with all matching hobby names.

How to search for a specific key in firebase without having a reference to that key

My database structure looks like this:
Structure
My reference is initialized like this:
let databaseRef = FIRDatabase.database().reference().child("Butikker")
When i run this function in viewdidload, my console prints: nil nil
func fetchNearByPlaces() {
databaseRef.observeSingleEvent(of: FIRDataEventType.value, with: { (snapshot) in
if let dictionary = snapshot.value as? [String: AnyObject] {
print(dictionary["Longtitude"], dictionary["Latitude"])
}
})
I want to print all the values that has the key: Longtitude and Latitude without referring to a specific path.
When observing a node in Firebase by .childAdded, it returns each node, one at a time and the snapshot children can be accessed directly.
When observing by .value however, the snapshot contains the parent nodes and all of the children. In that case, to get at each child node, iterate over the snapshot like this:
let databaseRef = self.ref.child("Butikker")
databaseRef.observeSingleEvent(of: .value, with: { (snapshot) in
for child in snapshot.children {
let snap = child as! DataSnapshot
let dictionary = snap.value as! [String: Any]
print(dictionary["Longitude"], dictionary["Latitude"])
}
})
also, in Firebase 4, instead of FIRDataEventType.value, just use .value

I need to know when firebase observation done completely

I am trying to observe multiple data at once using firebase, the observation block keeps looping until it fetchs all the data. I need to know when it is actually done so I can execute another block. How can I do that?
databaseRef.child("First_Secondary_Grade").child("0").child("0").queryOrderedByKey().observe(.childAdded, with: {
(snapshot) in
if let dictoinary = snapshot.value as? [String: AnyObject] {
let dataofthequsation = structofthedata()
dataofthequsation.setValuesForKeys(dictoinary)
}
})
i think i figured it out
let databaseRef = FIRDatabase.database().reference()
var gotitall = 0
// First you need to observe single event to get the real count of children in swift 3 observe will count the keys inside a child. That's why!
databaseRef.child("First_Secondary_Grade").child("0").child("0").observeSingleEvent(of:.value, with:{ (snap) in
gotitall = Int(snap.childrenCount)
databaseRef.child("First_Secondary_Grade").child("0").child("0").observe(.childAdded, with: {
snapshot in
if let dictoinary = snapshot.value as? [String: AnyObject] {
let dataofthequsation = structofthedata()
dataofthequsation.setValuesForKeys(dictoinary)
self.dataofthequsation.append(dataofthequsation)
// this is will run when the block runs through all children
if gotitall == self.dataofthequsation.count {
completion()
}
}
})
})

Resources