Read Data from Firebase Swift

Read data from firebase swift

You are listening for the .value event, but your block is dealing with a single item at a time so use .childAdded event for that.

let ref = FIRDatabase.database().reference().child("users").child("user").child(username)

ref.observeSingleEvent(of: .childAdded, with: { (snapshot) in
if let userDict = snapshot.value as? [String:Any] {
//Do not cast print it directly may be score is Int not string
print(userDict["score"])
}
})

Note: In Swift use native Dictionary instead of NSDictionary

Swift: how to retrieve data from firebase?

To read data from Firebase you attach a listener to a path which is what creates a FIRDatabase reference. A FIRDatabaseReference represents a particular location in your Firebase Database where there is a key-value pair list of children. So in your case, you have created a Firebase reference to the key "wins" which only points to a value and not a key-value pair. Your reference was valid up to this point:

    ref = Database.database().reference().child(passUserID) 

//did you mean FIRDatabase and not Database??

This FIRDatabaseReference points to the key passUserID which has a key-value pair list of children ["wins":"7"] and ["losses":"8"] (NOTE: a key is always a string). So from your FIRDatabase reference, you create your observer as follows and read the value of "wins":

   ref?.observe(.childAdded, with: { (snapshot) in

//Convert the info of the data into a string variable
if let getData = snapshot.value as? [String:Any] {

print(getData)

let wins = getData["wins"] as? String

print("\(wins)")

}

})

The Child added event will fire off once per existing piece of data, the snapshot value will be an individual record rather than the entire list like you would get with the value event. As more items come in, this event will fire off with each item. So if "losses" is the first record you might not get the value of "wins". Is this what you are trying to achieve? If what you really wanted to know is the value of "wins" at that particular location and to know if this value has ever changed you should use the .value observer as follows:

    ref?.observe(.value, with: { (snapshot) in

//Convert the info of the data into a string variable
if let getData = snapshot.value as? [String:Any] {

let wins = getData["wins"] as? String

print("\(wins)") //check the value of wins is correct

}

})

Or if you just wanted to get the know the value of wins just once and you are not worried about knowing if there any changes to it, use the "observeSingleEvent" instead of "observe".

EDIT

I saw your image and now realize you might also have a problem with your reference. Your ref should actually be something like:

    ref = FIRDatabase.database().reference().child("game-").child(passUserID)

You have obscured what "game" is but a valid reference to "wins" will include it.

SECOND EDIT

I will add the following so you can properly debug the problem. Use this pattern to observe the value and see if you get an error returned and what is says:

        ref.observe(.value, with: { (snapshot) in

print(snapshot)

}, withCancel: { (error) in

print(error.localizedDescription)

})

Normally it will give you an error if you cannot access that Firebase location because of a database rule. It will also be a good idea to see if print(snapshot) returns anything as above.

Retrieve firebase data from swift

Try something like that:

Database.database().reference()
.child("Stations").
observeSingleEvent(of: .value, with: { (snapshot) in
guard let value = snapshot.value as? [String: Any] else {
return
}

var stations = [Station]()
for (key, value) in values {
guard let station = value as? [String: Any],
let adresse = station["adresse"] as? String,
let codePostat = station["codePostat"] as? String else {
continue
}
stations.append(Station(adresse: adresse, codePostat: codePostat))
}

// if you have some completion return retrieved array of stations
completion(stations)
})

struct Station {

private let adresse: String
private let codePostat: String

init(adresse: String, codePostat: String) {

self.adresse = adresse
self.codePostat = codePostat
}
}

Get the data from all children in firebase using swift

You'll want to attach the observer one level higher in the JSON, and then loop over the child nodes:

ref.observeSingleEvent(of: .value) { snapshot in
for case let child as FIRDataSnapshot in snapshot.children {
guard let dict = child.value as? [String:Any] else {
print("Error")
return
}
let latitude = dict["Latitude"] as Any
let longtitude = dict["Longtitude"] as Any
print(longtitude)
print(latitude)
}
}

Loop syntax taken from Iterate over snapshot children in Firebase, but also see How do I loop all Firebase children at once in the same loop? and Looping in Firebase

How to read data from firebase

try this:-

ref = Database.database().reference()

ref.child("club").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]
{
if let clubName = childSnapshot["name"] as? String {
print(clubName)
}
}
}

}
}

Swift Firebase get Data to Class Object

Well You need to change your datamodel first. You dont need to store id value in , 12345 in this case. you can already fetch the key. Also, in /users/chats, you just can just save the chat id as either chat1 : IBDrbfku887BLIY or IBDrbfku887BLIY : true. You can always fetch them through value or the key respectively.

And in your chat document, you just need to reference the user id, i.e just get them and store them as user1 and user2. You can add more users if your usecase requires more.

Reconfigure your Data Model as follows.

Sample Image

Now You need 2 Objects Users and Chats as follows :

Users.swift

class User : NSObject {

private var _name: String!
private var _username: String!
private var _userid: String!
private var _userRef: DatabaseReference!

var name: String! {
get {
return _name
} set {
_name = newValue
}
}

var username : String! {
get {
return _username
} set {
_username = newValue
}
}

var userid: String! {
get {
return _userid
} set {
_userid = newValue
}
}

var userRef: DatabaseReference! {
get {
return _userRef
} set {
_userRef = newValue
}
}

init(userid: String, userData: Dictionary<String, Any>){

self._userid = userid

_userRef = Database.database().reference().child(_userid)

if let username = userData["username"] as? String {
self._username = username
}

if let name = userData["name"] as? String {
self._name = name
}

}

}

Chats.swift

class Chat : NSObject {

private var _chatid: String!
private var _user1: String!
private var _user2: String!
private var _chatRef: DatabaseReference!

var user1: String! {
get {
return _user1
} set {
_user1 = newValue
}
}

var user2 : String! {
get {
return _user2
} set {
_user2 = newValue
}
}

var chatid: String! {
get {
return _chatid
} set {
_chatid = newValue
}
}

var chatRef: DatabaseReference! {
get {
return _chatRef
} set {
_chatRef = newValue
}
}

init(chatid: String, chatData: Dictionary<String, Any>){

self._chatid = chatid

_chatRef = Database.database().reference().child(_chatid)

if let user = chatData["users"] as? Dictionary<String, Any> {
if let user1 = user["user1"] as? String {
self._user1 = user1
}
if let user2 = user["user2"] as? String {
self._user2 = user2
}
}

}

}

The major issue/or an overlooked issue here is the type of the data. In the /users, you id 12345 will be of type String. But when you fetch the same from /chats, it returns as Int. This downloads the value but never converts it. Always take care while seeding/testing your data.

To fetch the user's credentials just reference that through another query. This is what you can do :

var allUsers = [User]()
var allChats = [Chat]()

func viewDidLoad() {
super.viewDidLoad()
fetchAllChats()
}

func getUser(from userId: String, completion: @escaping (User) -> Void) {

Database.database().reference().child("users").child(userId).observeSingleEvent(of: .value, with: { snapshot in
if let datasnap = snapshot.value as? Dictionary<String, Any> {
let user = User(userid: userId, userData: datasnap)
completion(user)
}
})
}

func fetchAllChats() {
Database.database().reference().child("chats").observeSingleEvent(of: .value, with: { snapshot in
allChat.removeAll()
if let snapshot = snapshot.value as? Dictionary<String, Any> {
for snap in snapshot {
if let chatd = snap.value as? Dictionary<String, Any> {
let chat = Chat(chatid: snap.key, chatData: chatd)
self.allChats.append(chat)
}
}
}
// collectionview.reloadData() <--------- only if required.
})
}

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let chatData = allChats[indexPath.row]
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: CellId, for: indexPath) as! Cell
getUser(from: chatData.user1) { user in
cell.label.text = user.usernme
}
return cell
}

Swift retrieve data from Firebase

You are observing the childAdded event.

So your closure will only be executed when a new value I inserted into Users/Advertisements.

Try this code instead

Database
.database()
.reference()
.child("Users")
.child(Auth.auth().currentUser!.uid)
.child("Advertisements")
.queryOrderedByKey()
.observeSingleEvent(of: .value, with: { snapshot in

guard let dict = snapshot.value as? [String:Any] else {
print("Error")
return
}
let imageAd = dict["imageAd"] as? String
let priceAd = dict["priceAd"] as? String
})

The closure will be executed only once and "almost" immediately.

How to read data from Firebase realtime database using loop

There's a bunch of ways to get to that data; I'll show two, a coding solution and then an alternative structure solution

Coding solution:

The ID's are unknown but the path to the parent node of those ID's is. So create a reference to the most-known key (the parent, 11) and then read the child nodes underneath.

Assemble them into an array of DataSnapshots (to keep the order) and then iterate over that array, getting the child data at numberOfTargets.

func readNumberOfTargets() {
let mayRef = self.ref.child("2020").child("May") //self.ref points to my firebase
let dayRef = mayRef.child("11")
dayRef.observeSingleEvent(of: .value, with: { snapshot in
let childSnaps = snapshot.children.allObjects as! [DataSnapshot]
for child in childSnaps {
let mainSnap = child.childSnapshot(forPath: "main")
let numTargets = mainSnap.childSnapshot(forPath: "numberOfTargets")
print(child.key, numTargets)
}
})
}

and the output

Jan Snap (numberOfTargets) 80
borys Snap (numberOfTargets) 77
ftfvdf Snap (numberOfTargets) 99

Note that it looks like the numberOfTargets is being stored as a string so use this if that's the case

let numTargets = mainSnap.childSnapshot(forPath: "numberOfTargets").value as? String ?? "No Targets"

if it's being stored as an Int, use this

let numTargets = mainSnap.childSnapshot(forPath: "numberOfTargets").value as? Int ?? 0

Alternative Structure Solution:

It's common practice to denormalize your data in NoSQL databases and also using compound keys to get to it. In this case, we'll do both and create a seperate node that contains a highly flattened structure that's super easy to get to

TargetCount
2020_May_11_Jan: 80
2020_May_11_borys: 77
2020_May_11_ftfvdf: 99

So when you want the target count for each node, it can just be read based on the path. In other words, when this node is created

2020
May
11
Jan

they key 'Jan' (the unknown key per your question) is returned when that node is created. So at the same time write that path to the TargetCount node

TargetCount
2020_May_11_Jan: 80

As you iterate over the child nodes, you'll know the unknown by descontstucting the key string

2020_May_11 and then the Jan value is 80

You could also do this if you want to isolate the specific dates

TargetCount
2020_May_11
Jan:80
borys: 77
ftfvdf: 99

How to configure Firebase for Swift and read data out

The problem is that you are trying to access Firestore with Firebase methods.

"But then I try to access my data and it gives me nothing!" It gives you nothing because there is no data in Firebase, all your data is in Firestore.

See this guide for Firestore: https://firebase.google.com/docs/firestore/quickstart

and this one to understand the differences between Firebase and Firestore:
https://firebase.google.com/docs/database/rtdb-vs-firestore



Related Topics



Leave a reply



Submit