Getting all the users same child in Firebase (Swift) - ios

I am currently building an app in Firebase and I want to get all the users pineapple rate.
This is the tree:
user1: uid1 {
fruits: {
apple: 3
pineapple: 5
}
}
user2: uid2 {
fruits: {
apple: 4
pineapple: 2
}
}
I tried this code:
var ref = FIRDatabase.database().reference()
ref.queryOrderedByChild("fruits")
.observeSingleEventOfType(.Value, withBlock: { (snapshot) in
if ( snapshot.value is NSNull ) {
print("not found")
} else {
for child in snapshot.children {
let rate = child.value["pineapple"] as! String
print(rate)
}
}
})
But it gives me an error of unwrapping Nil.
Picture of the structre:

This is supposed to be like this
var ref = FIRDatabase.database().reference()
ref.queryOrderedByChild("user2")
.observeSingleEventOfType(.Value, withBlock: { (snapshot) in
if snapshot.exists() {
for child in (snapshot.value?.allValues)! {
if let fruits = child["Fruits"] as? [String:String]{
let rate = fruits["pineapple"]
print(rate)
}
}
}
})

It seems this just needs a deep query?
let ref = self.myRootRef.child("parent_node")
ref.queryOrderedByChild("Fruits/pineapple").observeSingleEventOfType(.Value, withBlock: {
snapshot in
if ( snapshot.value is NSNull ) {
print("not found")
} else {
for child in snapshot.children {
let key = child.key as String
let dict = child.value["Fruits"] as! NSDictionary
let pineapple_count = dict["pineapple"] as! Int
print("key = \(key) count = \(pineapple_count)")
}
}
})
and the output is
key = uid_1 count = 1
key = uid_0 count = 3
key = uid_2 count = 21

Try out this code below (Xcode 8.3.3, Swift 3 and Firebase 3 )
var ref = Database.database().reference().child("fruits")
ref.observeSingleEvent(of: .value, with: {
(snapshot) in
if let fruitPost = snapshot.value as? Dictionary<String,AnyObject> {
for(key, value) in fruitPost {
if let fruitData = value as? Dictionary<String,AnyObject> {
if let fruits = fruitData["pineapple"] as? String{
let rate = fruits
print(rate)
}
}
}
}
Goodluck mate!

Related

How to wait until firebase realtime database return data iOS Swift [duplicate]

This question already has answers here:
Returning data from async call in Swift function
(13 answers)
Closed 2 years ago.
I'm a newbie to both Swift and Firebase, I don't Firebase is async connection and I don't know the best practice how to control the the program to wait for the return of data from Firebase and then proceed to next line.
Here is my code: I need to make two queries and once they were completed, then move on the the function prepareSelectedDftList, but the problem is the function is get called before Firebase return. Appreciated to give me some guidance how to fix it. Thank you.
ref = Database.database().reference().child(dftNode)
ref.observe(DataEventType.value, with: { (snapshot) in
// need to consider the workshop is still empty or not?
if snapshot.childrenCount > 0 {
// get defect list
for defect in snapshot.children.allObjects as! [DataSnapshot] {
let defectObj = defect.value as? [String: AnyObject]
let defectId = defect.key
let defectName = defectObj?["name"]
self.tmpDisplayDefectIdList.append(defectId)
self.tmpDisplayDefectNameList.append(defectName as! String)
self.tmpDefectSelected.append(0)
}
}
})
selectedDft = Database.database().reference().child(node)
selectedDft.queryOrderedByKey().queryEqual(toValue: passInCompId).observe(.childAdded, with: { (snapshot) in
for child in snapshot.children {
let snap = child as! DataSnapshot
let tmpkey = snap.key as String?
self.selectedDftId.append(tmpkey!)
}
self.prepareSelectedDftList()
})
You need to do like this:
ref = Database.database().reference().child(dftNode)
ref.observe(DataEventType.value, with: { (snapshot) in
// need to consider the workshop is still empty or not?
if snapshot.childrenCount > 0 {
// get defect list
for defect in snapshot.children.allObjects as! [DataSnapshot] {
let defectObj = defect.value as? [String: AnyObject]
let defectId = defect.key
let defectName = defectObj?["name"]
self.tmpDisplayDefectIdList.append(defectId)
self.tmpDisplayDefectNameList.append(defectName as! String)
self.tmpDefectSelected.append(0)
}
}
selectedDft = Database.database().reference().child(node)
selectedDft.queryOrderedByKey().queryEqual(toValue: passInCompId).observe(.childAdded, with: { (snapshot) in
for child in snapshot.children {
let snap = child as! DataSnapshot
let tmpkey = snap.key as String?
self.selectedDftId.append(tmpkey!)
}
self.prepareSelectedDftList()
})
})
OR Call both in parallelly
var i = 0
ref = Database.database().reference().child(dftNode)
ref.observe(DataEventType.value, with: { (snapshot) in
// need to consider the workshop is still empty or not?
if snapshot.childrenCount > 0 {
// get defect list
for defect in snapshot.children.allObjects as! [DataSnapshot] {
let defectObj = defect.value as? [String: AnyObject]
let defectId = defect.key
let defectName = defectObj?["name"]
self.tmpDisplayDefectIdList.append(defectId)
self.tmpDisplayDefectNameList.append(defectName as! String)
self.tmpDefectSelected.append(0)
}
}
i = i + 1
if i == 2{
self.prepareSelectedDftList()
}
})
selectedDft = Database.database().reference().child(node)
selectedDft.queryOrderedByKey().queryEqual(toValue: passInCompId).observe(.childAdded, with: { (snapshot) in
for child in snapshot.children {
let snap = child as! DataSnapshot
let tmpkey = snap.key as String?
self.selectedDftId.append(tmpkey!)
}
i = i + 1
if i == 2{
self.prepareSelectedDftList()
}
})

How would I iterate over all keys to get specific child value?

I am trying to iterate over all keys under "Timetable" to get the key value and Name of those that have an approved value of "Yes".
So for the following JSON structure:
Timetable
Pikes_Lane_Primary_School_Bolton_UK
Approved: Yes
Name: Pikes Lane Primary School
Essa_Academy_Bolton_UK
Approved: No
Name: Essa Academy
Ladybridge_High_School_Bolton_UK
Approved: Yes
Name: Ladybridge High School
My desired output would be:
Pikes_Lane_Primary_School_Bolton_UK
Pikes Lane Primary School
Ladybridge_High_School_Bolton_UK
Ladybridge High School
This is the best I've managed to do over the last few hours:
let schoolDatabase = Database.database().reference().child("Timetable")
schoolDatabase.observeSingleEvent(of: .value, with: { (snapshot) in
for child in snapshot.children {
let schoolID = child as! DataSnapshot
//print(schoolID.key)
for grandchild in schoolID.children {
let varOne = grandchild as! DataSnapshot
print(varOne.key)
}
}
})
This brings back the following:
Approved
Name
Approved
Name
Approved
Name
let schoolDatabase = Database.database().reference().child("Timetable")
schoolDatabase
.queryOrdered(byChild: "Approved")
.queryEqual(toValue: "Yes")
.observeSingleEvent(of: .value, with: { (snapshot) in
let children = snapshot.children
.compactMap { $0 as? DataSnapshot }
children.forEach { tuple in
print(tuple.key)
if let tupleDictionary = tuple.value as? [String: Any] {
let name = tupleDictionary["Name"] as? String
print(name ?? "-")
}
}
}
)
Or if you are interested only in names (without key):
let schoolDatabase = Database.database().reference().child("Timetable")
schoolDatabase
.queryOrdered(byChild: "Approved")
.queryEqual(toValue: "Yes")
.observeSingleEvent(of: .value, with: { (snapshot) in
let children = snapshot.children
.compactMap { $0 as? DataSnapshot }
.compactMap { $0?.value as? [String: Any]}
.compactMap { $0["Name"] as? String }
children.forEach { name in
print(name)
}
}
)
Finally got there in the end!
let schoolDatabase = Database.database().reference().child("Timetable")
schoolDatabase.observeSingleEvent(of: .value, with: { (snapshot) in
for child in snapshot.children {
let schoolID = child as! DataSnapshot
let stringApproved = schoolID.childSnapshot(forPath: "Approved").value
let stringSchoolName = schoolID.childSnapshot(forPath: "Name").value
if stringApproved as? String == "Yes" {
print(schoolID.key)
print((stringSchoolName)!)
print((stringApproved)!)
}
}
})

How to append values to a dictionary after a firebase query?

In the below code I am trying to append string uids to a dictionary the problem is when I do so it seems like the dict is reset after each iteration. How can I fix this?
func getFollowing() {
self.ref.child("Following").child(uid)
.observeSingleEvent(of: .value, with: { (snapshot) in
if let data = snapshot.value as? [String:[String : Any]] {
for key in data.keys {
var dict = (UIApplication.shared.delegate as! AppDelegate).usersCurrentUserIsFollowing
dict[key] = true
print(dict, " this is gtteh dict now dhfsakflk")
}
}
})
}
I was able to solve my problem by doing the following:
func getFollowing() {
self.ref.child("Following").child(uid)
.observeSingleEvent(of: .value, with: { (snapshot) in
var usersData = ["":true]
if let data = snapshot.value as? [String:[String : Any]] {
for key in data.keys {
usersData[key] = true
}
var dict = (UIApplication.shared.delegate as! AppDelegate).usersCurrentUserIsFollowing
dict = usersData
}
})
}

I cannot get the data from my snapshot to load into my tableView cells

ref = Database.database().reference()
ref.child("Clubs").observe(.value, with: { (snapshot : DataSnapshot) in
print("clubs: \(snapshot)")
if let childSnapshot = snapshot.value as? [String : AnyObject] {
print("myClubs: \(childSnapshot)")
From this point, i am unable to get the "name" and "bannerImage" to load into my tableView
if let clubName = childSnapshot["name"] as? String, let banner = childSnapshot["bannerImage"] as? String {
print(clubName)
print(banner)
let club = Club(name: clubName, image: banner)
print("new club success: \(club)")
self.nightClubs.append(club)
self.tableView.reloadData()
}
Use this:-
ref = Database.database().reference()
ref.child("Clubs").observe(.value, with: { (snapshot) in
print("clubs: \(snapshot)")
if(snapshot.exists()) {
let array:NSArray = snapshot.children.allObjects as NSArray
for obj in array {
let snapshot:FIRDataSnapshot = obj as! FIRDataSnapshot
if let childSnapshot = snapshot.value as? [String : AnyObject] {
print("myClubs: \(childSnapshot)")
if let clubName = childSnapshot["name"] as? String, let banner = childSnapshot["bannerImage"] as? String {
print(clubName)
print(banner)
let club = Club(name: clubName, image: banner)
print("new club success: \(club)")
self.nightClubs.append(club)
}
}
}
self.tableView.reloadData()
}
}

Swift Firebase Access child snapshot data

I am currently trying to access data from a child snapshot in Swift. Here is my code that I have (which worked before the Swift 3/Firebase update):
if let achievements = snapshot1.childSnapshotForPath("Achievements").children.allObjects as? [FIRDataSnapshot] {
if achievements.count != 0 {
if let val = achievements[0].value!["somevalue"] as? Int {
self.dict["somevalue"] = val
}
}
So what I am trying to do here, is to create a variable of a child snapshot (achievements), and access child snapshot data from it. The achievements[0] will simply return the very first value. However, this doesn't seem to work. How should I approach this?
I am currently doing this inside a snapshot already (of 'observeType:.ChildAdded')
My Firebase DB looks like this:
Achievements{
randomId1 {
somevalue : somevalue
}
randomId2 {
somevalue2 : somevalue2
}
}
Updated code:
func loadData() {
ref.child("Players").observe(FIRDataEventType.childAdded) { (snapshot:FIRDataSnapshot) in
if let value = snapshot.value as? [String:AnyObject], let username = value["Username"] as? String {
}
if let value = snapshot.value as? [String:AnyObject], let ranking = value["Rank"] as? String {
}
if let childSnapshot = snapshot.childSnapshot(forPath: "Achievements").children.allObjects as? [FIRDataSnapshot] {
if childSnapshot.count != 0 {
if let achievement1 = childSnapshot[0].value!["Rookie"] as? String {
print(achievement1)
}
}
}
}
}
JSON Tree:
Players {
PlayerID {
Username
Rank
Achievements {
Rookie: yes
}
}
Try :-
if let childSnapshot = snapshot.childSnapshot(forPath: "Achievements") as? FIRDataSnapshot{
if let achievementDictionary = childSnapshot.value as? [String:AnyObject] , achievementDictionary.count > 0{
if let achieveMedal = achievementDictionary["Rookie"] as? String {
print(achieveMedal)
}
}
}

Resources