I have problem reading from Firebase in Swift.
Here is my Firebase database:
and here is my code:
var ref: FIRDatabaseReference!
override func viewDidLoad() {
super.viewDidLoad()
NSLog("Reading from DB")
ref = FIRDatabase.database().reference()
self.ref?.child("Frais").observeSingleEvent(of: .value, with: { (snapshot) in
let value = snapshot.value as? [String: Int]
var frpx1 = (value?["frpx1"]!)!
var frpx10 = (value?["frpx10"]!)!
var frpx11 = (value?["frpx11"]!)!
var frpx12 = (value?["frpx12"]!)!
var frpx13 = (value?["frpx13"]!)!
var frpx14 = (value?["frpx14"]!)!
var frpx15 = (value?["frpx15"]!)!
var frpx16 = (value?["frpx16"]!)!
})
print(frpx1)
print(frpx10)
print(frpx11)
print(frpx12)
print(frpx13)
print(frpx14)
print(frpx15)
print(frpx16)
}
I did not find the problem.
I do not have the data from database in frpx1, ..., frpx16.
Your code have a couple of minor issues:
you are casting the returned value to [String: Int] when you should be using [String: Any] instead since not all values are String based.
you are printing the results outside the completion handler. You need to wait the handler to be called to then read the results (i.e., when the method observeSingleEvent returns Firebase is still processing your request).
Fixing both issues should get you going:
...
self.ref?.child("Frais").observeSingleEvent(of: .value, with: {
(snapshot) in
guard let value = snapshot.value as? [String: Any] else {
print("Snapshot type mismatch: \(snapshot.key)")
return
}
let frpx1 = value["frpx1"]
let frpx10 = value["frpx10"]
let frpx11 = value["frpx11"]
...
print(frpx1)
print(frpx10)
print(frpx11)
...
})
PS. I also improved your coding style a little to help prevent further issues ;)
Related
I'm trying to get quotes out of Firebase, and I'm struggling. Granted, I also have no idea what I'm doing. I could use some help!
In Firebase, my quotes are set up like :
root
--> quotes
--> quoteID
--> quoteText, quoteAttribution
I'm trying to pull quotes down from Firebase, add them to a local array (to later put in a dictionary), and then pull a random one to use in the app. I hope to put the quoteText into quoteLabel.text, and the quoteAttribution into authorLabel.text. I found this solution in another StackOverflow issue, but it throws the following error at line 43:
Could not cast value of type 'NSNull' (0x10f549740) to 'NSDictionary' (0x10f549178).
2018-07-21 22:49:50.241473-0400 Wavefully[72475:1126119] Could not cast value of type 'NSNull' (0x10f549740) to 'NSDictionary' (0x10f549178).
Does anyone have any tips for how I might pull quoteText and quoteAttribution out of Firebase to use in my app?
Here's my code:
class ViewController: UIViewController {
class quoteClass {
var uid = ""
var quote = ""
var author = ""
}
#IBOutlet weak var quoteLabel: UILabel!
#IBOutlet weak var authorLabel: UILabel!
var ref: DatabaseReference?
var databaseHandler: DatabaseHandle?
var quotesArray = [quoteClass]()
override func viewDidLoad() {
super.viewDidLoad()
// Set the reference to Firebase
ref = Database.database().reference()
let quotesRef = ref?.child("quotes")
quotesRef?.observeSingleEvent(of: .value, with: { (snapshot) in
for _ in snapshot.children {
let quoteSnap = snapshot
let quoteKey = quoteSnap.key
let thisQuoteRef = quotesRef?.child("quoteID")
thisQuoteRef?.observeSingleEvent(of: .value, with: { (quoteSnap) in
let singlequoteSnap = quoteSnap
let quoteDict = singlequoteSnap.value as! [String:AnyObject]
let quote = quoteDict["quoteText"]
let author = quoteDict["quoteAttribution"]
let aQuote = quoteClass()
aQuote.uid = quoteKey
aQuote.quote = quote as! String
aQuote.author = author as! String
print(aQuote.quote)
print(aQuote.author)
print(aQuote.uid)
self.quotesArray.append(aQuote)
})
}
})
let singleQuote = quotesArray.randomItem()!
print(singleQuote.uid)
print(singleQuote.quote)
print(singleQuote.author)}}
Thanks a ton for helping!
Alternatively you can also use your data by casting it into NSDictionary like below:
let dictionary = snapshot.value as? NSDictionary
let quote = dictionary["quoteText"] as? String ?? ""
Okay, so I was making it way harder than it needed to be. I did this, and it's working:
func grabData() {
ref = Database.database().reference()
ref?.child("quotes").observe(.value, with: {
snapshot in
for snap in snapshot.children.allObjects as! [DataSnapshot] {
guard let dictionary = snap.value as? [String:AnyObject] else {
return
}
let quote = dictionary["quoteText"] as? String
let author = dictionary["quoteAttribution"] as? String
let id = dictionary["quoteID"] as? String
self.quoteLabel.text = quote
self.authorLabel.text = author
print(quote!)
print(author!)
print(id!)
}
})
}
Now, I just have to call grabData() in my viewDidLoad to get a quote. Up next: randomize what quote is shown. Oh, and probably store it in Core Data or Realm for local storage. 🤓
Thanks for stopping by!
I have a small dataset in Firebase database, but unfortunately, I can't get read value from list correctly. Here is the structure of the database.
I just need to get the value of day and reference it to var. Thanks in advance.
var collnum = ""
ref = Database.database().reference()
let collid = ref.child("collid").child("day")
collid.observeSingleEvent(of : .value, with : {(Snapshot) in
print(Snapshot)
if let snapDate = Snapshot.value as? String{
collnum = snapDate
print(snapDate)
}
})
let database = FIRDatabase.database().reference()
database.child("collid").queryOrderedByKey().observe(.value, with:
{
if let value = snapshot.value as? [String: AnyObject]
{
let ui = value["day"] as! String
print(ui)
}
}
You can do something like this to read the data. This will read the data from the database and put into an array, allowing you to read the data.
I'm trying to pass data that I've retrieved from my firebase database into a field of my singleton. The data is received via closure, and in that closure I'm passing some data into my singleton's properties. If I print the data structure inside the closure (after everything's been assigned) I get the output I'm expecting, but if I print it at the end of the initializer after all the data should've been passed in, it's empty.
import Foundation
import Firebase
class EmployeeList {
static let sharedInstance = EmployeeList()
var employeeDictionary: [String: [EmployeeData]]
var ref: DatabaseReference!
private init() {
employeeDictionary = [String: [EmployeeData]]()
ref = Database.database().reference()
ref.child("employeeList").observeSingleEvent(of: .value, with: { snapshot in
if let dictionary = snapshot.value as? [String: [String: AnyObject]] {
for subsection in dictionary {
var subsectionEmployees: [EmployeeData] = []
for item in subsection.value {
self.ref.child("employeeList/\(subsection.key)/\(item.key)").observeSingleEvent(of: .value, with: { employeeSnapshot in
let employeeObject = EmployeeData(snapshot: employeeSnapshot)
subsectionEmployees.append(employeeObject)
self.employeeDictionary[subsection.key] = subsectionEmployees
//print(self.employeeDictionary) This print statement prints out the expected data every time another employee is appended
})
}
}
}
//print(self.employeeDictionary) This print statement prints an empty data structure
})
}
}
get data from Firebase as Below
var messagedata = [String:AnyObject]()
let databaseReff = Database.database().reference().child("message")
databaseReff.queryOrdered(byChild: "fromId").queryEqual(toValue: self.recieverId).observe(.value, with: { snapshot in
if snapshot.exists(){
self.messagedata = snapshot.value! as! [String : AnyObject]
self.getAllMessagesSent(snapshot: self.messagedata)
} else
self.getAllMessagesSent(snapshot: self.messagedata) //Function Created
}
})
pass the data fetched from Clousre to a dictionary and pass that dict to a function and do anything you want to do or use escaping blocks
func getAllMessagesSent(snapshot: [String:AnyObject]) {
//data is here
}
Alright so here is my code:
var locationCount: Int!
var latLocation = [Double]()
var longLocation = [Double]()
func polyline() {
var coords = [CLLocationCoordinate2D]()
databaseHandle = databaseRef.child("RunList").child(runName).child("locations").observe(.value, with: { (snapshot) in
self.locationCount = Int(snapshot.childrenCount)
print(self.locationCount)
func getLocations() {
var i = 0
while i < self.locationCount {
self.databaseHandle = self.databaseRef.child("RunList").child(self.runName).child("locations").child("\(i)").observe(.value, with: { (snapshot) in
let locData = snapshot.value as? [String: AnyObject]
let lat = (locData?["lat"] as? Double)!
let long = (locData?["long"] as? Double)!
self.latLocation.append(lat)
self.longLocation.append(long)
})
i = i + 1
}
}
getLocations()
})
}
So the problem I am facing is that when I try to call the two arrays latLocation and longLocation outside of the code blocks/polyline(), they return as empty. So for example, if I try to print them in viewDidLoad(), they both print as empty arrays. How can I fix this? The same issue is with locationCount too, if I print that outside of the code blocks then I get an error where the value is nil because it has no value, but inside of the code block it works perfectly fine. This is really confusing me and I think there is a simple solution to it that I have overlooked.
I'm trying to filter results from a Firebase database with a structure like this one.
chats
chatId
messages
messageId
userId: true
I need two queries, one that returns only messages with existing child userId (if it exists it will always be true), the other that returns only messages without it.
I'm trying with this two references and observing .childAdded event:
let messagesWithUser = FIRDatabase.database().reference(withPath: "chats").child(chat.id).child("messages").queryOrdered(byChild: userId).queryEqual(toValue: true).ref
let messagesWithoutUser = FIRDatabase.database().reference(withPath: "chats").child(chat.id).child("messages").queryOrdered(byChild: userId).queryEqual(toValue: NSNull()).ref
Currently the .childAdded event returns all messages without filtering.
In response to Dmitriy:
func blueRewardBalance(completeBlock: (value: Double) -> Void) {
let userRef = FIRAuth.auth()?.currentUser?.uid
var rewardBalance : Double! = 0.00
let purchaseRef = FIRDatabase.database().reference(withPath: "Reward/\(userRef!)")
purchaseRef.queryOrdered(byChild: "abc").observe(.value, with: { snapshot in
let dataSnapshot = snapshot.value as! [String: AnyObject]
rewardBalance = dataSnapshot["rewardCardBalance"] as! Double!
completeBlock(rewardBalance)
})
}
Found out the problem. I was using FIRDatabaseReference instead of FIRDatabaseQuery to observe changes...
Thank you Nicola. I need implement previous method into my function, but blueRewardBalance request parameters.
func blueRewardTransaction(purchaseValue: Double) {
let newBalance = blueRewardBalance(completeBlock: //what I need paste here?) - purchaseValue
let userRef = FIRAuth.auth()?.currentUser?.uid
let firebaseRef = FIRDatabase.database().reference()
firebaseRef.child("Reward/\(userRef!)").updateChildValues(["rewardCardBalance": newBalance])
}