Can I manipulate FDatasnapshot once I have queried for it? - ios

I want to be able to do some custom filtering on the Datasnapshot I get back. I don't think I can create a complex query to accomplish the result I want.
Is this possible to do and if so, what is the best way of parsing the snapshot?
EDIT:
I am using SwiftyJSON and this is how I ended up parsing it:
standbyRef.observeSingleEventOfType(.Value, withBlock: { snapshot in
// do some stuff once
println(snapshot.value)
self.parseJson(snapshot.value as NSDictionary)
})
func parseJson(var snapshot:NSDictionary!){
let json = JSON(snapshot)
for (key: String, subJson: JSON) in json {
// key to standby users
println(key)
// one object at a time
println(subJson)
}
}

Firebase accepts all the data in JSON format only. When you get a Datasnapshot of any perticular node of Firebase, you get the complete data below that node, which is in all a JSON only.
Once you get the Datasnapshot JSON you can parse it using any JSON library, depending on the platform you use.
You can refer here Datasnapshot Methods for more info.

Without any additional library, you can also do something like that:
if let email = snapshot.value["email"] as? String {
user.email = email
}
Or if you want to iterate over all values:
let enumerator = snapshot.children
while let child = enumerator.nextObject() as? FDataSnapshot {
println(child.key)
println(child.value)
}

Related

Could not cast value of type '__NSDictionaryM' (0x1f0c63860) to 'NSString' (0x1f0c70290) Swift

I'm reading data from the Firebase database which I then sorted in an alphabetical order.
I want to read the keys under the Scenario tree, but not the entire data under it.
Then I want to put the keys in the gradePickerValues1 variable.
Firebase Database Tree
2
Scenario
Yeni Senaryo
OffTime: "12:12"
OnTime: "12:12"
Yeni Senaryo2
OffTime: "12:12"
OnTime: "12:12"
MainActivity
var gradePickerValues1 : [String] = []
#objc func getSenaryo(){
let ref = Database
.database()
.reference()
.child(self.chipFieldText.text!)
.child("Scenario")
ref.observe(.value) { (snapshot) in
for group in snapshot.children {
self.gradePickerValues1.append((group as AnyObject).key)
}
}
}
Instead of
let userDict = userSnap.value as! String
do
let userDict = userSnap.value as! [String: [String: String]]
as your "Scenario" holds a dictionary with a structure of [Name: [Time: String]].
If you want to get "12:12" of OffTime of Yeni Senaryo from this dictionary, you can do something like this:
let value = userDict["Yeni Senaryo"]!["OffTime"]!
If the data base structure is more complex, you should use [String: Any] instead and use if let syntax to perform optional typecast.
EDIT: If you only want to read "Yeni Senaryo" and not the values under, it is simply not possible with Firebase.
See Best practices for data structure:
Avoid nesting data
Because the Firebase Realtime Database allows nesting data up to 32 levels deep, you might be tempted to think that this should be the default structure. However, when you fetch data at a location in your database, you also retrieve all of its child nodes. In addition, when you grant someone read or write access at a node in your database, you also grant them access to all data under that node. Therefore, in practice, it's best to keep your data structure as flat as possible.
Anyway, if you don't need the nested values and only the names, you can do
let userDict = userSnap.value as! [String: Any]
let userNames = Array(userDict.keys)
and the array of names as Strings will be stored in userNames.
EDIT2:
Don't typecast group as AnyObject.
AnyObject.key is not the key you want.
for group in snapshot.children {
guard let value = value as? DataSnapshot else { continue }
self.gradePickerValues1.append(value.key)
}

get a KEY, given a value, from Firebase in Swift

Have a registry of users, and we would like to input an email address, then return the UID.
Is there a way to do this in swift?
We would like the function to return this.
like we'd input user#user.com into the function and it will return gSVeU6....
Any tips and suggestions are really appreciated man.
Here is what the firebase JSON tree looks like
func findFriendsUIDFromFirebase(selectedFriendsEmail: String) {
print("Hey from findFriendsUIDFromFirebase called")
fir.child("registeredUsersOnPlatform").observeSingleEvent(of: .value, with: { (snapshot) in
if snapshot.exists() {
guard let allTheUsers = snapshot.value as? [String:String] else {
print("Something is wrong with this snapshot")
return
}
if let selectedUserUIDFromFirebase = allTheUsers.someKey(forValue: selectedFriendsEmail) {
//DO STUFF
basically in this way we download everything locally then loop through the dictionary, but am looking for a better way, one that doesn't involving downloading the whole thing. Maybe something with a .equals()?
At the same time, for some reason when printing the dictionary, it seems to be stuck at 100 key-value pairs. when there are like 300ish pairs on the actual table. It's some clipping somewhere.
You would need to perform a Firebase query for the specific value you are looking for:
let queryEmail = "Userone#user.com"
fir.child("registeredUsersOnPlatform").queryOrderedByValue().queryEqual(toValue: queryEmail).observeSingleEvent(of: .value) { (querySnapshot) in
for result in querySnapshot.children {
let resultSnapshot = result as! DataSnapshot
print (resultSnapshot.key)
}
}
You can also limit the amount of query results you would like with .queryLimited(toFirst: x)
If you want to get Key when create User in firebase you can get them in user callBack data like:
Auth.auth().createUser(withEmail: email, password: pwd) { (user, _) in
print(user?.uid)
}
Else if you want to get key from value in normal lists data so that use queryEqualToValue then print snapshot's child key

How to get the value of a key in firebase - iOS

so this is an image of my JSON tree:
my JSON TREE
Question:
I wanted to know how can I check if the username, let's say, sean exists in the usernames. I currently have no idea on how to implement this.
What I've tried:
The key of usernames child is "theUsernameOf-userUID", and that causes the problem as userUID is dynamic and different from each user (from firebase auth), therefore I can't use:
.queryOrderedByChild("theUsernameOf-userUID").queryEqual(toValue: self.usernameTextBox.text!)
The key of usernames child can't be static like theUsername as it would only be able to have 1 value / not able to generate more node.
Thank you so much, sorry if I didn't explain clearly enough.
I would like to modify your DB structure as current one is not the correct to perform this query.
It should be like below:
Always use auto incremented keys for queries. Here usernames -> autoGeneratedKey -> yourData (Dictionary - Key-Value pair) Now you can easily check the existence of any key.
let ref = defaultDB.reference.child("usernames")
ref.queryOrdered(byChild: "username").queryEqual(toValue: "sean").observeSingleEvent(of: DataEventType.value) { (snapshot) in
if snapshot.exists() {
print("exists")
}
else {
print("doesn't exist")
}
}
Output: exists
This is the correct way to do so. Just checking for snapshot.exists() will do the job for you.
When you observe any reference in firebase, you get a DataSnapshot in return. The snapshot has a children enumerator property on which you can enumerate each child. Each of the child will be another DataSnapshot. Now, each snapshot has key and value. You want the user name? It's in the value property:
let databaseRef = Database.database().reference(withPath: "usernames")
databaseRef.observe(.value) { (snapshot) in
snapshot.children.forEach({ (child) in
if let child = child as? DataSnapshot, let value = child.value {
print(value) //"Sean", "Yuh"
// here you can check for your desired user
}
})
}
Here is how you can do it
Set the database reference to the usernames node. For example db.ref.child("usernames")
Now parse the snapshot using for loop
let usernames = snapshot.value as! NSDictionary
Now the for loop
for username in usernames{
if username.value == "Sean"{
// do whatever you want here
}
}
You could also:
Make a firebase call to usernames and make that:
let usernames = snapshot.value as? [String: AnyObject],
then all you have to do is something like
if let keyExists = usernames[YOURUSERNAMECHECKSTRING] {
//It's true
}
Just another way of looking at it.
Try This code will Help you you dont need to change your firebase structure
In Swift
Database.database().reference(withPath: "users").queryOrdered(byChild: "usernames").queryEqual(toValue: "yourUserName").observe(.value)
{ (snapshot:DataSnapshot) in
if snapshot.valueInExportFormat() is NSDictionary
{
// User is exits
}
else
{
}
}
In Objective c
[[[[[FIRDatabase database] referenceWithPath:#"users"] queryOrderedByChild:#"usernames"] queryEqualToValue:#"your User Name"] observeSingleEventOfType:FIRDataEventTypeValue withBlock:^(FIRDataSnapshot * _Nonnull snapshot)
{
if ([snapshot.valueInExportFormat isKindOfClass:[NSDictionary class]])
{
// User is exits
}
else
{
}
}];

Firebase Sort array of class by value

I'm using Firebase. In my app, I get a child value by passing in a bottleID and get the details for that value from the snapshot. I then assign the details to an object of MyCollection_Class and add it to an array. After getting every single bottle value, I want to sort that array using the created_at tag before reloading the table view. Please advise me on how to sort the array of objects by a specific instance variable.
let Collection = MyCollection_Class()
FireBaseConstants.AUCTIONS_REF.child(bottleID).observeSingleEvent(of: .value, with: { (snap) in
if !(snap.value is NSNull) {
Collection.id = bottle_dict["id"] as? String
Collection.item_number = bottle_dict["item_number"] as? Int
Collection.created_at = bottle_dict["created_at"] as? String
if !(self.MyCollectionsIDArr.contains(Collection.id! as String)) {
self.MyCollectionsArr.append(Collection)
self.MyCollectionsIDArr.append(Collection.id!)
// I want to sort the MyCollectionsArr using created_at here
self.tbl_Latest.reloadData()
}
}
})
You can just retrieve the data already sorted from Firebase by using
queryOrderedByChild.
An example would be:
ref.child(bottleID).queryOrderedByChild("created_at").queryEqualToValue(0).observe SingleEventOfType(.Value, withBlock: { snap in
print("snap \(snap)")
expectation.fulfill()
})

Firebase data comparison swift

hi I'm new to swift and i'm using firebase in my app. i want to get all the data under a child from firebase database and compare it with an already existing array to find the missing values and load them in tableview i had added the code i use to perform this and in that the for loop is called every time when new child is found and i want to perform that for loop after getting all the values from the firebase database. is there any way to perform this or is there any way to know whether the firebase had retrieved all the data. Thanks in advance
func fetchUsers()
{
ingredientMasterArr.removeAll()
refhandle1 = ref.child("ingredients").observeEventType(.ChildAdded, withBlock:
{ (snapshot) in
if let dictionary = snapshot.value as? [String : String]
{
let ingredients = IngredientsClass()
ingredients.id = dictionary["id"]
ingredients.ingredient_name = dictionary["ingredient_name"]
// ingredients.category
ingredientMasterArr.append(ingredients)
}
FilteredIngMasterArr.removeAll()
let temp = IngredientsClass()
for MasterID in ingredientMasterArr
{
if (ShopIngKeysArr .contains(MasterID.id!)){
print("if",MasterID.ingredient_name)
}
else
{
print("else",MasterID.ingredient_name)
temp.id = MasterID.id
temp.ingredient_name = MasterID.ingredient_name
FilteredIngMasterArr.append(temp)
}
}
self.tbl_ingMaster.reloadData()
})
}
Using the .Value event type instead of .ChildAdded should give you all the results at once:
refhandle1 = ref.child("ingredients").observeEventType(.Value, ...
Read the firebase documentation on retrieving data for more details.

Resources