Query data is deleted after exiting Firebase block - ios

I have a firebase query running to retrieve a user's stored search radius before passing the result to GeoFire. It looks like this:
var searchRadius = Double()
ref.childByAppendingPath("/users/\(ref.authData.uid)/searchRadius").observeEventType(.Value, withBlock: { snapshot in
self.searchRadius = snapshot.value as! Double
print(self.searchRadius)
})
print(self.searchRadius)
The first print line prints out my stored radius (in this case 4.xxxxxx), but it prints after the second print line outside the brackets. So my result in my console ends up looking like:
0.0
4.xxxxxxxx
Why is this? I encountered a similar problem with firebase and solved it with an ObserveReadyWithBlock, but this is my first time seeing the issue in Firebase.
Thanks for any help!

Related

Display the name of a user using Firebase

What I want to do is to make a top header in the app with the name of the user displayed in a label. I know everything to do this except how to reference their name. To give more clarity this is what I want (even though this doesn't work in the newest version of xcode);
let userName = Auth.auth().currentUser.name
// so this is the string of the users name
I know this seems really simple and there is probably an easy way to do it that I'm not sure of. Thanks for the help!
This is how I access my firebase realtime database and read from it:
let ref = Database.database().reference()
ref.child("Username").observeSingleEvent(of: .value) {(snapshot:DataSnapshot) in
let userName = snapshot.value as? String
Print(userName)
}
Instead of where I put "Username", you can replace this with the name of the node under which the value you want to output is stored. And if this node is the child node of another, you can continue to add .child("XXX") to the line of code.
e.g.
ref.child("Account").child("Username").observeSingleEvent(of: .value) {(snapshot:DataSnapshot) in
It's tucked away a little, in providerData, which is an instance of UserInfo...
let user = Auth.auth().currentUser
let userName = user.providerData.displayName

Download URL from Firestore Storage in wrong order

i have a little problem with my Firebase-Storage.
In my storage I have some pictures like:
"apple.jpg", "blueberry.jpg", "melon.jpg"...
In my Swift-Code I have an Array with Fruit-Names like:
["Apple", "Blueberry", "Melon"]
In my function I loop through my Apple-Name-Array and if I print the fruitsRef I get the following result:
gs://myapp-5313d.appspot.com/sort/apple.jpg
gs://myapp-5313d.appspot.com/sort/blueberry.jpg
gs://myapp-5413d.appspot.com/sort/melon.jpg
but in my fruitsRef.downloadURL-Method I get random ordered results:
Optional(https://firebasestorage.googleapis.com/v0/b/myapp-5413d.appspot.com/o/sort%2Fblueberry.jpg?alt=media&token=5047d133-b37e-49d2-ae6c-59be5e7cafbf)
Optional(https://firebasestorage.googleapis.com/v0/b/myapp-5413d.appspot.com/o/sort%2Fmelon.jpg?alt=media&token=5047d133-b37e-49d2-ae6c-59be5e7cafbf)
Optional(https://firebasestorage.googleapis.com/v0/b/myapp-5413d.appspot.com/o/sort%2Fapple.jpg?alt=media&token=5047d133-b37e-49d2-ae6c-59be5e7cafbf)
func setUrlArray(sorts: Array<String>) {
for currentSort in sorts {
let storage = Storage.storage()
let storageRef = storage.reference()
let fruitsRef = storageRef.child("sort/" + currentSort.lowercased().replacingOccurrences(of: " ", with: "") + ".jpg")
print(fruitsRef)
fruitsRef.downloadURL { url, error in
print(url)
}
}
}
how is that possible?
kind regards,
doomsweb
The issue has to do with the asynchronous nature of the downloadURL function on your fruitsRef variable. When you are iterating the array, you are synchronously printing out the reference to the image (print(fruitsRef)), and then also kicking off an asynchronous task (downloadURL).
You've guaranteed that the for loop will print out the fruitsRef in a particular order, since you are looping through the array one at a time - however, you have no guarantees with regard to which order your Firebase storage will respond to your network requests.
From the server's perspective, you are asking for three different assets at basically the same time (since your app will loop through the array of three elements very quickly), and the server will try to respond to each request as soon as it's able. So as soon as any one of those assets is returned to your app, the print(url) line is hit.
I solved the issue now with a Little Trick. My fruits name Array was already sorted alphabetically. So I have sorted the array with the links now also alphabetically. Now the order is correct

Swift Firebase Query - No Results in Snapshot

I am trying to query our LCList object by the "name" value, as shown in this image. The name key is just on the next level below the object. There are no additional levels to any of its other values.
The code I am using to do the query is: (Keeping in mind listsRef points to the LCLList object)
listsRef.queryOrderedByKey()
.queryStarting(atValue: name)
.observeSingleEvent(of: .value, with: { snapshot in
The snapshot from this query comes back with nothing in its value. I have tried ordering the results by the name value as well, with the same result. I have inspected the values returned with only the queryOrderedByKey() method call, and they match what is in the database. The issue is obviously with the .queryStarting(atValue:) method call.
I'm really puzzled by why this is not working as the same query pointed to our LCLUser object, with nearly the same structure, does get results. The two objects exist at the same level in the "Objects" directory seen in the previous image.
Any help at this point would be appreciated. I'm sure there's something simple I'm missing.
That query won't work for the Firebase structure shown in the question.
The query you have is as follows, I have added a comment on each line detailing what each line does
listsRef.queryOrderedByKey() //<- examine the key of each child of lists
.queryStarting(atValue: name) //<- does that keys' value match the name var
.observeSingleEvent(of: .value, with: { snapshot in //do it once
and your current data looks like this
Objects
LCLLists
node_x
creator: "asdasa"
name: "TestList3"
node_y
creator: "fgdfgdfg"
name: "TestList"
so what's happening here is the name var (a string) is being compared to the value of each key (a Dictionary) which cannot be equal. String ≠ Dictionary
key value
["node_x": [creator: "asad", name: "TestList3"]
For that query to work, your structure would need be be like this
Objects
LCLLists
node_x: "TestList3"
node_y: "TestList"
My guess is you want to stick with your current structure so, suppose we want to query for all names that are 'TestList' using your structure
let ref = self.ref.child("LCLLists") //self.ref is a class var that references my Firebase
let query = ref.queryOrdered(byChild: "name").queryEqual(toValue: "TestList")
query.observeSingleEvent(of: .value, with: { snapshot in
print(snapshot)
})
and the result is a printout of node_y
node_y
creator: "fgdfgdfg"
name: "TestList"

Firebase QueryOrderedByChild along with EqualToValue and StartingAtValue Combination

I am trying to query Firebase by a Child that is equal to a certain value BUT start the snapshot at a specific post key.
Data Structure:
projectName
-posts
-postKey1
-storeId: 1
-postKey2
-storeId: 2
-postKey3
-storeId:3
-postKey4
-storeId:2
-postKey5
-storeId:3
-postKey6
-storeId:2
Example:
I am trying to queryOrderedByChild("storeId") with queryEqualToValue("2") BUT I would like the snapshot to start at "postKey4" when it is returned in its order.
My Current Query:
ref.queryOrderedByChild("storeId").queryEqualToValue("\(myId)").observeEventType(.Value, withBlock: {snapshot in
I know that you can't call queryEqualToValue: after queryStartingAtValue, queryEndingAtValue or queryEqualToValue after previously called but I need that queryEqualToValue to get my storeId. Any help is greatly appreciated!
You can pass a second argument into queryStartingAtValue that specifies the key at which to start.
ref.queryOrderedByChild("storeId")
.queryStartingAtValue(2, childKey: "postKey4")
.queryEndingAtValue(2)
.observeEventType(.Value, withBlock: {snapshot in
for childSnapshot in snapshot.children {
print(childSnapshot.key!!
}
})
This prints:
postKey4
postKey6
I must admit this is the first time I use the second argument to queryStartingAtValue, so I might not understand it completely yet.
The reason you can't use queryEqualToValue is that that will only return a single key, which is not what you want.

How to get all results from a Firebase Query in one block

I'm having a hard time working with Firebase query results. With the following code:
ref.queryOrderedByChild("gender")
.queryEqualToValue("female")
.observeEventType(.ChildAdded, withBlock: { snapshot in
print("result: \(snapshot) ")
})
The "result" is printed 3 times. I would expect a single array of all of the results (similar to a query on Parse) versus this being printed 3 separate times.
The end goal here is to append all of the results to an Array. However, I don't know how to do that, since I can't see any way of knowing how many elements will come back from the server.
I assume there must be something simple I am missing here.
It appears it was something simple I was missing. Changing the event type from .ChildAdded to .Value resolves the issue. Hopefully this will help someone else...
var resultArray:[AnyObject] = []
ref.queryOrderedByChild("gender")
.queryEqualToValue("female")
.observeEventType(.Value, withBlock: { snapshot in
for item in snapshot.children{
resultArray.append(item)
}
print("Results Array: \(resultArray)")
print("Results Array Count: \(resultArray.count)")
})

Resources