Reputation: 399
Im trying to get all the imageURLs for all activities that are for a specific user (UserId). the content of the snapshot include the correct entries, however the imageURL is not appended to imageArray. What am I doing wrong?
// Get all images for a specific user
func getImagesForUser(userId:String, handler: @escaping (_ imageArray: [String]) -> ()) {
var imageArray = [String]()
REF_ACTIVITY.queryOrdered(byChild: "userId").queryEqual(toValue: userId).observe(.value, with: { snapshot in
dump(snapshot)
guard let data = snapshot.value as? NSDictionary else { print("else was returned"); return }
let imageURL = data["imageURL"] as? String ?? ""
imageArray.append(imageURL)
handler(imageArray)
})
}
Output from dump(snap)
Snap (-L2RDXTKANzD8YGpPl92) {
gearId = asfasfsf;
imageCount = 3;
imageURLs = {
1 = "http://www.foo.com";
2 = "http://www.foo2.com";
3 = "http://www.foo3.com";
};
killCount = 10;
kills = 12;
likeCount = 2;
likes = {
fas86q39rasf = 1;
};
userId = NhZZGwJQCGe2OGaNTwGvpPuQKNA2;
}
Snap (-L2RDXTKANzD8YGpPl92) {
gearId = asfasfsf;
imageCount = 3;
imageURLs = {
1 = "http://www.foo.com";
2 = "http://www.foo2.com";
3 = "http://www.foo3.com";
};
killCount = 10;
kills = 12;
likeCount = 2;
likes = {
fas86q39rasf = 1;
};
userId = NhZZGwJQCGe2OGaNTwGvpPuQKNA2;
}
Update - output of Dict
24 elements
▿ 0 : 2 elements
- key : "commentCount"
- value : 1
// removed some info
...
▿ 12 : 2 elements
- key : "imageURLs"
▿ value : 4 elements
- 0 : <null>
- 1 : https://firebasestorage.googleapis.com/v0/b/shoota-179610.appspot.com/o/activity_image%2FCA6F4C93-8F5F-456C-9FD6-F2EACC444739?alt=media&token=522d957b-dedf-4bdc-9cbc-1de581284393
- 2 : https://firebasestorage.googleapis.com/v0/b/shoota-179610.appspot.com/o/activity_image%2FCA6F4C93-8F5F-456C-9FD6-F2EACC444739?alt=media&token=522d957b-dedf-4bdc-9cbc-1de581284393
- 3 : https://firebasestorage.googleapis.com/v0/b/shoota-179610.appspot.com/o/activity_image%2FCA6F4C93-8F5F-456C-9FD6-F2EACC444739?alt=media&token=522d957b-dedf-4bdc-9cbc-1de581284393
▿ 13 : 2 elements
- key : "imageURL"
- value : https://firebasestorage.googleapis.com/v0/b/shoota-179610.appspot.com/o/activity_image%2FCA6F4C93-8F5F-456C-9FD6-F2EACC444739?alt=media&token=522d957b-dedf-4bdc-9cbc-1de581284393
▿ 14 : 2 elements
- key : "killCount"
- value : 10
Upvotes: 0
Views: 545
Reputation: 35648
There are a few issues with the code in the question:
It appears you just want to get the data one time but that observe will stay attached and any time there's a change anywhere in that node that matches the query, you will be notified. If you just want it one time, use observeSingleEvent instead
Also, you are returning multiple nodes with that query - and those will need to be worked with one at a time via a loop to iterate over the returned data.
Here's a very simplified example of that technique. Note there is no error checking; for example if one of the returned nodes doesn't contain an imageURL key that should be handled with a guard or perhaps a nil-coalescing operator (??) to assign a default in that case.
let activitesRef = self.ref.child("activities")
let query = activitesRef.queryOrdered(byChild: "userId").queryEqual(toValue: userId)
query.observeSingleEvent(of: .value, with: { snapshot in
for child in snapshot.children {
let snap = child as! DataSnapshot
let dict = snap.value as! [String: Any]
let url = dict["imageURL"] as? String ?? "no url"
print(url)
}
})
Edit:
This code assumes a structure like this
activities
activity_0
userId: "uid_0"
imageURL: "www.someurl.com"
activity_1
userId: "uid_1"
imageURL: "www.anotherurl.com"
activity_2
userId: "uid_0"
imageURL: "www.coolurl.com"
in the above case two nodes will be returned in the snapshot and the above code will iterate over those nodes and print the url from each.
www.someurl.com
www.coolurl.com
Another Edit:
Based on some follow up comments, it appears there are multiple urls for each user. Here's an updated Firebase structure to match:
activities
activity_0
userId: "uid_1"
urls
url_0: "www.someurl.com"
url_1: "www.anotherurl.com"
url_2: "www.coolurl.com"
activity_1
userId: "uid_1"
urls
url_0: "www.thisurl.com"
url_1: "www.thaturl.com"
url_2: "www.ou812url.com"
Note that arrays should be avoided in NoSQL databases so we're using url_0, url_1 but in reality those node keys should be created with childByAutoId.
And then the code to query for all nodes for uid_1 and print their url's
let activitesRef = self.ref.child("activities")
let query = activitesRef.queryOrdered(byChild: "userId").queryEqual(toValue: userId)
query.observeSingleEvent(of: .value, with: { snapshot in
for child in snapshot.children {
let snap = child as! DataSnapshot
print(snap.key)
let urlSnap = snap.childSnapshot(forPath: "urls")
for url in urlSnap.children {
let aUrlSnap = url as! DataSnapshot
let key = aUrlSnap.key
let val = aUrlSnap.value as! String
print(" key: \(key) url: \(val)")
}
}
})
and finally the output
activity_0
key: url_0 url: www.someurl.com
key: url_1 url: www.anotherurl.com
key: url_2 url: www.coolurl.com
activity_1
key: url_0 url: www.thisurl.com
key: url_1 url: www.thaturl.com
key: url_2 url: www.ou812url.com
Upvotes: 1