how to receive / update data when it changes (Firebase) in swift - ios

I have some data stored on firebase and when somebody adds to my data, through my app I want to receive and update my data. I looked at the google docs and it said to something like this...
databaseRef.child("Leaderboard").queryOrderedByKey().observe(.childChanged, with: {
snapshot in
let value = snapshot.value as? NSDictionary
// put data into variables
let playerName = value?["playerName"] as! String?
}
But for some reason it returns nil, I know I have my hierarchy right. Why is it returning nil?

let playerName: String = value!["playerName"] as? String

Related

Retrieving data from firebase Realtime Datbase with SwiftUI Xcode 11

For a few days I have been trying to read my data from firebase without success.
Indeed it is a set of tables also containing tables.
This function is to retrieve the subjects and at the same time the paragraphs
func getSubjects() {
let subjectRef = database.child("subjects")
subjectRef.observe(.childAdded, with: { (snapshot) in
for child in snapshot.children {
print(snapshot)
if let snapshot = child as? DataSnapshot,
let subject = Subject(snapshot.value)
//subjectList.append(subject)
// print("Data : \(subject)")
}
})
}
This is the firebase screen
Console screen
On Android I didn't have this problem, but since I'm new to iOS, I'm having a hard time coping.
Any help will be welcome. Thank you
At the moment, you are observing the database for constant changes and it will only run when a child/value has been added into the place you're currently checking, for this you may only want to retrieve a value once, and every time that view is loaded then it will fetch from the database again. It's a lot more efficient and less costly. You may want something like this:
ref = Database.database().reference()
ref.child("subjects").child("0").child("paragraphs").child("0").observeSingleEvent(of: .value, with: { (snapshot) in
let value = snapshot.value as? NSDictionary
let location = value["location"] as? NSDictionary
let title= value?["title"] as? String ?? ""
let text = value?["text"] as? String ?? ""
let latitude = location?["latitude"] as? String ?? ""
let longitude = location?["longitude "] as? String ?? ""
}) { (error) in
print(error.localizedDescription)
}
You think each child with nodes inside it as an array, or a json object. You can cast them into an NSDictionary and use that cast to access values inside them if they're nested.
If they're not nested and in the same level as the place you're watching in the database ref, like for instance, above we are looking in the subjects > 0 > paragraphs > 0 node within the database. Title is a value inside that node and not a child so we can simply get the value of title from the database through the data snapshot given back.
I recommend reading the Docs, they're very good and easy to understand when working with different OS/languages.

Retrieving data from database and displaying? IOS

I'm new in Firebase and the Pods. I'm having trouble retrieving data from the Database. I think I'm doing something wrong with the libraries that Firebase has. My app runs good but doesn't show the results in the console, can someone explain why is not getting the information from my database. As well any resource from a different server will help a lot. Here is what I have.
PS: Any other information let me know Thank you!!
As first you should change your observer DateType to .value, because the .childAdded will only be executed when a child is added.
Second you should loop through all your 'bestBuyLocations?' and fetch the lat and lons.
see example below:
let databaseRef = Database.database().reference().child("bestBuy")
databaseRef.observe(.value) { snapshot in
if let snapShotValue = snapshot.value as? NSDictionary {
for location in snapShotValue {
if let locationValues = location.value as? [String: Any] {
if let lon = locationValues["lon"] as? NSString {
print(lon)
}
if let lat = locationValues["lat"] as? NSString {
print(lat)
}
}
}
}
}
As per your attached image it is firestore not realtime database. The code you have added is for real-time database. please check firestore documentation to retrieve data.

type 'Any?' has no subscript members (using Firebase)

Every time I run this line of code it doesn't work, anyone who can give me a hand in what I can do too change it? Thanks for any help. :)
Below is the error I keep getting
Type Any? has no subscript members
var ref:FIRDatabaseReference?
var refHandle: UInt!
var postData = [String]()
override func viewDidLoad() {
super.viewDidLoad()
ref = FIRDatabase.database().reference()
refHandle = ref?.observe(FIRDataEventType.value, with:
{ (snapshot) in
let dataDict = snapshot.value as! [String: AnyObject]
print(dataDict)
})
let username: String = (FIRAuth.auth()?.currentUser?.uid)!
ref?.child("Users").child(username).observeSingleEvent(of: .value, with:
{ (snapshot) in
let username = snapshot.value!["Username"] as! String
self.usernameField.text = username
})
}
Two issues.
1. Optionals
This is Swift's way of making a variable be in one of two states namely, have a value or be nil. A variable can only be in one of these states. You make a variable an optional by adding a question mark in front of it.
2. Any
By declaring a variable to be of type Any, this means you're not explicitly stating its type during declaration. Firebase makes all of its returns be of type Any in order to give us developers the option of fiddling with the data as we so please hence less constraints on our side.
snapshot.value is of type Any but Firebase always returns a JSON tree and JSON trees can be represented as Dictionaries. So what should we do?
Since snapshot.value is an optional, we should check first to see if its nil.
If not nil, convert it to a dictionary then start accessing the respective elements inside it.
The code below does the job for you and I've added comments to explain what's happening.
ref?.child("Users").child(username).observeSingleEvent(of: .value, with:
{ (snapshot) in
// This does two things.
// It first checks to see if snapshot.value is nil. If it is nil, then it goes inside the else statement then prints out the statement and stops execution.
// If it isn't nil though, it converts it into a dictionary that maps a String as its key and the value of type AnyObject then stores this dictionary into the variable firebaseResponse.
// I used [String:Any] because this will handle all types of data types. So your data can be Int, String, Double and even Arrays.
guard let firebaseResponse = snapshot.value as? [String:Any] else
{
print("Snapshot is nil hence no data returned")
return
}
// At this point we just convert the respective element back to its proper data type i.e from AnyObject to say String or Int etc
let userName = firebaseResponse["Username"] as! String
self.usernameField.text = username
})

Access Data Outside of Closure, Firebase ObserveSingleEvent // SWIFT

When I first asked this question I hadn't really done my research. But after 20+ hours on this, I have structure exactly like in Firebase docs. But, I can't access any of the data outside of the closure. Here is the struct where the data should be written in to:
struct UserStruct {
let name : String!
let age : String!
}
And when it gets called, everything is written perfect in the database, inside the closure it doesn't print nil, it does print the actual value obviously. I have already tried
DispatchQueue.main.async {
}
But that didn't work either, somebody guide me! Any help is appreciated, this is my last issue with Firebase.
let currentUser = FIRDatabase.database().reference(withPath: "users").child((FIRAuth.auth()!.currentUser?.uid)!)
currentUser.observeSingleEvent(of: .value, with: { snapshot in
let value = snapshot.value as? NSDictionary
let name = value?["name"] as? String
let age = value?["age"] as? String
self.userAdded.insert(UserStruct(name: name, age: age), at: 0) // 1
let user = UserStruct.init(name: name, age: age) // 2
print("1 \(user.name)")
print("2 \(self.userAdded[0].name!)")
})
I wrote two ways of getting the data, number two(2) is the way Firebase suggests, but I can't even get a hold of user outside the closer like I can with the Struct.
Your user object that you create in the closure gets deallocated when the closure finishes what it has to do. As #Jay said in the comment, you need to store the data that you get in your closure in a variable outside of your closure. A quick and dirty way to test this out would be to create a variable in the class you're in and assign the user you create in your closure to that variable and print it out to see if it worked:
//add a property in your class to store the user you get from Firebase
var retrievedUser: UserStruct?
let currentUser = FIRDatabase.database().reference(withPath: "users").child((FIRAuth.auth()!.currentUser?.uid)!)
currentUser.observeSingleEvent(of: .value, with: { snapshot in
let value = snapshot.value as? NSDictionary
let name = value?["name"] as? String
let age = value?["age"] as? String
let user = UserStruct.init(name: name, age: age)
//assign the user retrieved from Firebase to the property above
self.retrievedUser = user
//print the local copy of the retrived user to test that it worked
print(retrievedUser)
})

How to retrieve objects from firebase by key value

I'm new to firebase and I have such structure of my firebase project
I want to get all objects, that "Interested" value is equal to "men"
I wrote such code, to get all object sorted by interes value:
let thisUserRef = URL_BASE.childByAppendingPath("profile")
thisUserRef.queryOrderedByChild("Interest")
.observeEventType(.Value, withBlock: { snapshot in
if let UserInterest = snapshot.value!["Interest"] as? String {
print (snapshot.key)
}
}
But I receive nil.
you need to loop through all the key-value profiles
if let allProfiles = snapshot.value as? [String:AnyObject] {
for (_,profile) in allProfiles {
print(profile);
let userInterest = profile["Interest"]
}
}
Here _ is the key that is in the format KYXA-random string and profile will be the element for that key.
Edit:
There is querying for child values as per the docs.
Try thisUserRef.queryOrderedByChild("Interest").equalTo("men") and then using the inner loop that i specified in the answer
This is a basic query in Firebase. (Updated for Swift 3, Firebase 4)
let profileRef = self.ref.child("profile")
profileRef.queryOrdered(byChild: "Interest").queryEqual(toValue: "men")
profileRef.observeSingleEvent(of: .value, with: { snapshot in
for child in snapshot.children {
let dict = child as! [String: Any]
let name = dict["Name"] as! String
print(name)
}
})
The legacy documentation from Firebase really outlines how to work with queries: find it here
Legacy Firebase Queries
The new documentation is pretty thin.
Oh, just to point out the variable; thisUserNode should probably be profileRef as that's what you are actually query'ing.

Resources