Firebase Retrieving Data in Swift

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.

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
}
}

Firebase Retrieving Data in Swift

It gives you that warning message indexOn because you are doing a query.

you should define the keys you will be indexing on via the .indexOn
rule in your Security and Firebase Rules. While you are allowed to
create these queries ad-hoc on the client, you will see greatly
improved performance when using .indexOn

As you know the name you are looking for you can directly go to that node, without a query.

    let ref:FIRDatabaseReference! // your ref ie. root.child("users").child("stephenwarren001@yahoo.com")

// only need to fetch once so use single event

ref.observeSingleEventOfType(.Value, withBlock: { snapshot in

if !snapshot.exists() { return }

//print(snapshot)

if let userName = snapshot.value["full_name"] as? String {
print(userName)
}
if let email = snapshot.value["email"] as? String {
print(email)
}

// can also use
// snapshot.childSnapshotForPath("full_name").value as! String
})

Retrieve Data from Firebase using where Query in Swift 4

You need to add a query:

ref.queryOrdered(byChild: "videoid").queryEqual(toValue: "12345").observeSingleEvent(of: .value, with: { snapshot in

more info here:

https://firebase.google.com/docs/reference/swift/firebasedatabase/api/reference/Classes/DatabaseQuery#queryorderedbychild

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

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.

How to retrieve data from firebase properly with a url in Swift?

You didn't provide enough information, however, I think this might help you.

First, you need to add LiturgyFetcher to your DailyWorshipView:

@ObservedObject var liturgyFetcher = LiturgyFetcher()

Then you need a way to join DailyData with LiturgyData:

struct DailyData: Identifiable {
let id = UUID()
let name: String
let model: String
let text: String

// this is just the idea...
var title: String {
!model.isEmpty ? "\(name) (\(model))" : name
}
}

and filter liturgyFetcher.sermons variable to find your liturgy:

liturgyFetcher.sermons.first{ $0.title == dailydata.title }

Your DailyWorshipView may look like this (you may want to move filtering to the LiturgyFetcher):

struct DailyWorshipView: View {
@State private var model = DailyData.all()
@ObservedObject var liturgyFetcher = LiturgyFetcher()

var body: some View {
NavigationView {
List {
ForEach(model) { dailydata in
self.liturgyCell(dailydata: dailydata)
}
}
.navigationBarTitle(Text("Hours"))
}
}

func liturgyCell(dailydata: DailyData) -> some View {
NavigationLink(destination: LiturgyDetail(liturgy: liturgyFetcher.sermons.first{ $0.title == dailydata.title })) {
HStack {
Text(dailydata.name)
}
}
}
}

Then you can use LiturgyData in your LiturgyDetail view as desired:

struct LiturgyDetail: View {
let liturgy: LiturgyData?

var body: some View {
Text("\(liturgy?.title ?? "no liturgy found")")
}
}

How to retrieve data from all the Users using Firebase and Swift

Looks like you misspelled the location key for your dictionary:

let location = userDict["Location"] as! [String: AnyObject]

Replace it with:

let location = userDict["location"] as! [String: AnyObject]

You can always put a breakpoint at the print line and see what your location dictionary looks like with po location in console.

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
}

Trying to get data from firebase Swift

You are trying to return value out of completion handler.

Your function should be like:

private func findAverage(byUid uid: String, completion: @escaping (_ average: Int) -> Void) {
// ...
dbRef.observeSingleEvent(of: .value, with: { snapshot in
guard let dict = snapshot.value as? [String: Any] else {
return
}
totalRatings = dict["totalRatings"] as? Int ?? 0
amountOfRatings = dict["amountOfRatings"] as? Int ?? 1

completion((Int)(totalRatings / amountOfRatings))
})
}

Something like this, check Swift docs (about completion handlers etc.).



Related Topics



Leave a reply



Submit