What is the effect of Firebase Realtime Database .onDisconnect function being called multiple times? - firebase-realtime-database

Using the Firebase doc sample code, what happens in the server if config_disconnect() is called 5 times in a row?
Should I call .cancelDisconnectOperations() right beforehand to prevent duplicate actions?
func config_disconnect() {
let myConnectionsRef = Database.database().reference(withPath: "users/morgan/connections")
let lastOnlineRef = Database.database().reference(withPath: "users/morgan/lastOnline")
let connectedRef = Database.database().reference(withPath: ".info/connected")
connectedRef.observe(.value, with: { snapshot in
guard let connected = snapshot.value as? Bool, connected else { return }
let con = myConnectionsRef.childByAutoId()
con.onDisconnectRemoveValue()
con.setValue(true)
lastOnlineRef.onDisconnectSetValue(ServerValue.timestamp())
})
}
Thank you :)

Related

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.

How to query a child from another child. Firebase(SWIFT)

im developing a delivery app. So I have productos and popular products in firebase this way:
Products
PopularProducts(ID of the product as key and true as value)
How I can query only the products who are popular using those childs?
You need to get array of productosPopulares and then get each object.
let referenceToProductosPopulares = FIRDatabase.database().reference(withPath: "productosPopulares")
referenceToProductosPopulares.observeSingleEvent(of: .value, with: { snapshot in
if let value = snapshot.value as? NSDictionary {
let productosPopIds = value.allKeys as! [String]
// get every object
for id in productosPopIds {
let refToProd = FIRDatabase.database().reference(withPath: "productos").child(id)
refToProd.observeSingleEvent(of: .value, with: { snapshot in
// your value
})
}
} else {
print("productosPopulares")
}
})
Not perfect code. Should make more functions. But this is idea.
Hope it helps
You can query ordered by the esPopular child and only return the children with it equal to true.
let ref = Database.database().reference(withPath: "productos")
let query = ref.queryOrdered(byChild: "esPopular").queryEqual(toValue: true)
query.observe(.childAdded, with: { (snapshot) in
print(snapshot)
}) { (error) in
print(error)
}

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()
}
}
})
})

Firebase iOS .queryOrderedByChild and .queryEqualTo not working

I'm trying to filter results from a Firebase database with a structure like this one.
chats
chatId
messages
messageId
userId: true
I need two queries, one that returns only messages with existing child userId (if it exists it will always be true), the other that returns only messages without it.
I'm trying with this two references and observing .childAdded event:
let messagesWithUser = FIRDatabase.database().reference(withPath: "chats").child(chat.id).child("messages").queryOrdered(byChild: userId).queryEqual(toValue: true).ref
let messagesWithoutUser = FIRDatabase.database().reference(withPath: "chats").child(chat.id).child("messages").queryOrdered(byChild: userId).queryEqual(toValue: NSNull()).ref
Currently the .childAdded event returns all messages without filtering.
In response to Dmitriy:
func blueRewardBalance(completeBlock: (value: Double) -> Void) {
let userRef = FIRAuth.auth()?.currentUser?.uid
var rewardBalance : Double! = 0.00
let purchaseRef = FIRDatabase.database().reference(withPath: "Reward/\(userRef!)")
purchaseRef.queryOrdered(byChild: "abc").observe(.value, with: { snapshot in
let dataSnapshot = snapshot.value as! [String: AnyObject]
rewardBalance = dataSnapshot["rewardCardBalance"] as! Double!
completeBlock(rewardBalance)
})
}
Found out the problem. I was using FIRDatabaseReference instead of FIRDatabaseQuery to observe changes...
Thank you Nicola. I need implement previous method into my function, but blueRewardBalance request parameters.
func blueRewardTransaction(purchaseValue: Double) {
let newBalance = blueRewardBalance(completeBlock: //what I need paste here?) - purchaseValue
let userRef = FIRAuth.auth()?.currentUser?.uid
let firebaseRef = FIRDatabase.database().reference()
firebaseRef.child("Reward/\(userRef!)").updateChildValues(["rewardCardBalance": newBalance])
}

How to ensure that the data is not retrieved and appended as a whole each time a new entry is added?

func generateDataForRecents() {
if URLArrayStringThisSeason.count == 0 {
self.activityIndicator2.isHidden = false
self.activityIndicator2.startAnimating()
}
let databaseRef = FIRDatabase.database().reference()
databaseRef.child("palettes").queryLimited(toFirst: 100).observe(.value, with: { (snapshot) in
if let snapDict = snapshot.value as? [String:AnyObject]{
for each in snapDict as [String:AnyObject]{
let URL = each.value["URL"] as! String
self.URLArrayStringRecents.append(URL)
//print(self.URLArrayString.count)
//print(snapshot)
//let pictureTitle = each.value["title"] as! String
print(self.URLArrayStringRecents.count)
}
}
self.whatsNewCollectionView?.reloadData() //Reloads data after the number and all the URLs are fetched
self.activityIndicator2.stopAnimating()
self.activityIndicator2.isHidden = true
})
}
The following code does a retrieval of data each time the function is called, or when a new data is added.
This is extremely useful when the app is first started up or closed and then restarted. However, when the app is running, whenever a new entry is added, the code seemed to run again and thus appending twice the amount of new data.
For example, when there are already 15 entries identified and then suddenly a new entry is added, the array of the URL would contain 15+16 thus amounting to a total of 31.
How do I make it such that the new data is added to the array instead of adding the entire snapshot in?
You do that by listening for .childAdded events, instead of listening for .value:
var query = databaseRef.child("palettes").queryLimited(toFirst: 100)
query.observe(.childAdded, with: { (snapshot) in
let URL = snapshot.childSnapshot(forPath/: "URL").value as! String
self.URLArrayStringRecents.append(URL)
}
Since you have a limit-query, adding a 101st item means that one item will be removed from the view. So you'll want to handle .childRemoved too:
query.observe(.childRemoved, with: { (snapshot) in
// TODO: remove the item from snapshot.key from the araay
})
I recommend that you spend some time in the relevant documentation on handling child events before continuing.
Please check below method. I have use this method not getting any duplicate entry.
func getallNotes()
{
let firebaseNotesString: String = Firebase_notes.URL
let firebaseNotes = FIRDatabase.database().referenceFromURL(firebaseNotesString).child(email)
firebaseNotes.observeEventType(.Value, withBlock: { snapshot in
if snapshot.childSnapshotForPath("Category").hasChildren()
{
let child = snapshot.children
self.arrNotes = NSMutableArray()
self.arrDictKeys = NSMutableArray()
for itemsz in child
{
let childz = itemsz as! FIRDataSnapshot
let AcqChildKey : String = childz.key
if AcqChildKey == AcqIdGlobal
{
if (childz.hasChildren() == true)
{
let dictChild = childz.value as! NSMutableDictionary
self.arrDictKeys = NSMutableArray(array: dictChild.allKeys)
for i in 0..<self.arrDictKeys.count
{
let _key = self.arrDictKeys.objectAtIndex(i).description()
print(_key)
let dictData : NSMutableDictionary = NSMutableDictionary(dictionary: (dictChild.valueForKey(_key)?.mutableCopy())! as! [NSObject : AnyObject])
dictData.setObject(_key, forKey: "notesId")
self.arrNotes.addObject(dictData)
}
}
}
}
self.tableviewNote.reloadData()
}
})
}
As for the query for removed child,
query.observe(.childRemoved, with: { (snapshot) in
print(snapshot)
let URL = snapshot.childSnapshot(forPath: "URL").value as! String
self.URLArrayStringThisSeason = self.URLArrayStringThisSeason.filter() {$0 != URL}
self.thisSeasonCollectionView.reloadData()
})
it will obtain the URL of the removed child and then update the array accordingly.

Resources