I was trying to retrieve data from firebase. I can retrieve data from a single child. But how can I retrieve data from many child?
I tried this way
func fatchSchdual(){
ref.child("Products").child(productdetailes[myIndex].userId!).child("Schedule").child("0").observeSingleEvent(of: .value) { (snapshot) in
if snapshot.childrenCount > 0{
for Schdu in snapshot.children.allObjects as! [DataSnapshot]{
let schdual = Schdu.value as? [String: AnyObject]
let startTime = schdual?["start"]
let endTime = schdual?["end"]
if let StartTime = startTime{
self.publishTime.text = StartTime as? String
}
}
}
}
}
but I didn't get any data.
func fatchFacilities(){
ref.child("Products").child(productdetailes[myIndex].userId!).child("Facility").observeSingleEvent(of: .value) { snapshot in
for child in snapshot.children {
if let value = (child as! DataSnapshot).value as? [String : Any] {
let name = value["name"] as? String
let unit = value["unit"] as? String
let facility = Facility(name: name, unit: unit)
facilities.append(facility)
}
}
}
}
Related
Please find my code below. How can we append filter data on array from Firebase?
var childrenList = [DatabaseList]()
let ref = Database.database().reference(withPath: "Messages")
let query = ref.queryOrdered(byChild: "VideoID").queryEqual(toValue: "12345").observe(.value, with: { (snapshot) in
for childSnapshot in snapshot.children{
print(childSnapshot)
self.childrenList.append(snapshot)
}
})
DispatchQueue.main.async {
self.tableView.reloadData()
}
let ref = Database.database().reference(withPath: "Messages")
let query = ref.queryOrdered(byChild: "VideoID").queryEqual(toValue: "12345").observe(.value, with: { (snapshot) in
print(snapshot)
for (childSnapshotId, childSnapshotValue) in snapshot {
if let dataListDict = childSnapshotValue as? [String: AnyObject] {
//Init you newModel with the dataListDict here
let newModel = DatabaseList(dict: dataListDict)
print(childSnapshot)
self.childrenList.append(newModel)
}
}
DispatchQueue.main.async {
self.tableView.reloadData()
}
})
class DatabaseList : NSObject {
var messageBody : String?
var name : String?
var videoID : String?
init(dict: [String: AnyObject]) {
messageBody = dict["MessageBody"]
name = dict["Name"]
videoID = dict["videoID"]
}
}
Your query is correct but there are few mistakes in finishing block.
self.childrenList.append(snapshot) snapshot is an instance of DataSnapshot not a DatabaseList so you can not append it like this.
for childSnapshot in snapshot.children {
/// childSnapshot is an instance of DataSnapshot not a dictionary but its value will be
guard let data = (childSnapshot as! DataSnapshot).value else {continue}
let dataDict = data as! Dictionary<String, Any>
/// Initializing the new object of DatabaseList and passing the values from data
let list: DatabaseList = DatabaseList()
list.messageBody = dataDict["MessageBody"] as? String
list.name = dataDict["Name"] as? String
list.videoID = dataDict["VideoID"] as? String
/// This is correct, and now you can append it to your array.
childrenList.append(list)
}
Apart from this you will have to reload the tableView inside the finishing block not below the block because this is an asynchronous request and data will come later.
Also its always better to check the data existence. snapshot.exists().
One more suggestion if you want to fetch the data just once then do not use .observe use .observeSingleEvent instead. .observe will fire the block every time there is any change at this node.
Here is the full code snippet.
let query = ref.queryOrdered(byChild: "VideoID").queryEqual(toValue: "12345").observe(.value, with: { (snapshot) in
if !snapshot.exists() {
// Data doesn't exist
return
}
for childSnapshot in snapshot.children {
guard let data = (childSnapshot as! DataSnapshot).value else {continue}
let dataDict = data as! Dictionary<String, Any>
let list: DatabaseList = DatabaseList()
list.messageBody = dataDict["MessageBody"] as? String
list.name = dataDict["Name"] as? String
list.videoID = dataDict["VideoID"] as? String
childrenList.append(list)
}
/// Reload your tableView here
DispatchQueue.main.async {
self.tableView.reloadData()
}
})
And expecting the class model like below:
class DatabaseList: NSObject {
var messageBody: String?
var name: String?
var videoID: String?
}
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()
}
}
My app has a collection view which displays rows of photos/images from Firebase, and I'd like to have them load in the order they were added, with the newest posts at the top. I thought that using queryOrderedByKey did that by default, and that's what I used in my fetch function, but the posts are out of order.
This is how I'm fetching the posts currently:
func fetchPosts() {
let ref = FIRDatabase.database().reference()
ref.child("users").queryOrderedByKey().observe(.value, with: { snapshot in
let users = snapshot.value as! [String : AnyObject]
for (_, value) in users {
if let uid = value["uid"] as? String {
if uid == FIRAuth.auth()?.currentUser?.uid {
if let followingUsers = value["following"] as? [String : String] {
for (_, user) in followingUsers {
self.following.append(user)
}
}
self.following.append(FIRAuth.auth()!.currentUser!.uid)
ref.child("posts").queryOrderedByKey().observeSingleEvent(of: .value, with: { (snap) in
let postsSnap = snap.value as! [String : AnyObject]
for (_, post) in postsSnap {
if let userID = post["userID"] as? String {
for each in self.following {
if each == userID {
let posst = Post()
if let poster = post["poster"] as? String, let likes = post["likes"] as? Int, let pathToImage = post["pathToImage"] as? String, let postID = post["postID"] as? String {
posst.poster = poster
posst.likes = likes
posst.pathToImage = pathToImage
posst.postID = postID
posst.userID = userID
if let people = post["peopleWhoLike"] as? [String : AnyObject] {
for (_, person) in people {
posst.peopleWhoLike.append(person as! String)
}
}
posts.append(posst)
}
}
}
self.collectionView.reloadData()
}
}
})
ref.removeAllObservers()
}
}
}
})
}
How can I get the posts to sort by newest first?
EDIT 2: updated - now sorting from oldest -> newest
func fetchPosts() {
let ref = FIRDatabase.database().reference()
ref.child("users").queryOrderedByKey().observe(.value, with: { snapshot in
let users = snapshot.value as! [String : AnyObject]
for (_, value) in users {
if let uid = value["uid"] as? String {
if uid == FIRAuth.auth()?.currentUser?.uid {
if let followingUsers = value["following"] as? [String : String] {
for (_, user) in followingUsers {
self.following.append(user)
}
}
self.following.append(FIRAuth.auth()!.currentUser!.uid)
ref.child("posts").queryOrderedByKey().observeSingleEvent(of: .value, with: { (snap) in
for postSnapshot in snap.children.allObjects as! [FIRDataSnapshot] {
let value = postSnapshot.value as! [String : AnyObject]
if let userID = value["userID"] as? String {
for each in self.following {
if each == userID {
let posst = Post()
if let poster = value["poster"] as? String, let likes = value["likes"] as? Int, let pathToImage = value["pathToImage"] as? String, let postID = value["postID"] as? String {
posst.poster = poster
posst.likes = likes
posst.pathToImage = pathToImage
posst.postID = postID
posst.userID = userID
if let people = value["peopleWhoLike"] as? [String : AnyObject] {
for (_, person) in people {
posst.peopleWhoLike.append(person as! String)
}
}
posts.append(posst)
}
}
}
self.collectionView.reloadData()
}
}
})
ref.removeAllObservers()
}
}
}
})
}
Queries return a snapshot the matching child nodes in the order requested. That means that the results consists of three things:
the item keys
the item values
the order of the items relative to each other
But then the first thing you do with the snapshot is:
ref.child("posts").queryOrderedByKey().observeSingleEvent(of: .value, with: { (snap) in
let postsSnap = snap.value as! [String : AnyObject]
You convert the snapshot into a dictionary. And a dictionary only has space for two things: the keys and the values. So the order is lost at this point, since dictionaries have an undefined order.
The proper way to access the result in the order you requested is to use the snapshot's built-in collection of children to iterate over them:
ref.child("posts").queryOrderedByKey().observeSingleEvent(of: .value, with: { (snapshot) in
for postSnapshot in snapshot.children {
let value = postSnapshot.value as! [String : AnyObject]
This will loop over the matching children in the order you queries them.
I'm trying to get the value of multiple children of my snapshot in order to append my cellDataArray by name and speed.
My code is working for name, but not for speed..
ref = FIRDatabase.database().reference().child("BasicInfo")
let query = ref?.queryOrdered(byChild: "Operator")
query?.observeSingleEvent(of: .value, with: { (snapshot) in
for child in snapshot.children.allObjects as! [FIRDataSnapshot] {
let name = child.key
let speed = child.childSnapshot(forPath: "Speed")
self.cellDataArray.append(cellData(mainText: name, Speed: ""))
self.tableView.reloadData()
}
})
This is my Firebase structure:
Try to access the value property of FIRDataSnapshot to get the Speed.
for child in snapshot.children.allObjects as! [FIRDataSnapshot] {
let name = child.key
if let dic = child.value as? [String:Any], let speed = dic["Speed"] as? Int
let operator = dic["Operator"] as? String {
print(operator)
self.cellDataArray.append(cellData(mainText: name, Speed: "\(speed)"))
}
}
DispatchQueue.main.async {
self.tableView.reloadData()
}
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)
}
}
}