How to show data in a tableView with Firebase Realtime Database - swift

Can anyone try to explain the steps I need to do? I get a lot of errors when I try to define my database in Xcode.
dbRef.child("class").observeSingleEvent(of: .value, with:
{ (snapshot) in
let value = snapshot().value? as? [String: AnyObject]
let description = value? ["desciption"] as? [Any]
let owner = value? ["owner"] as? [Any]
let participant = value? ["participant"] as? [Any]
let time = value? ["time"] as? [Any]
print("description: \(String(describing: description))")
print("owner: \(String(describing: owner))")
print("participant: \(String(describing: participant))")
print("time: \(String(describing: time))")

You do not need the () on snapshot().value. Make it snapshot.value as? [String: AnyObject] and that will remove the error "Cannot call value of non-function type 'DataSnapshot'"
Basically the error can be taken literally. snapshot (which is type DataSnapshot) is not a function, so you can't call it as a function i.e snapshot()

Related

Firebase: cannot retrieve children if they are less than the specified number in queryLimited

I have the following function that gets invoked when a user scrolls conversation tableview, it works well but if the remaining children are less than the specified number it retrieves none! What is more interesting is that those values appear in print(snapshot.value) but not in print(child). How can I get all nodes even if they are less than the specified number?
Thank you.
func fetchBatch(betweenUser userID: String, fromTimestamp: Double , completion: #escaping([Message]) -> ()){
guard let currentUID = Auth.auth().currentUser?.uid else { return }
var messages = [Message]()
REF_MESSAGES.child(currentUID).child(userID).queryOrdered(byChild: "timestamp").queryEnding(atValue: fromTimestamp).queryLimited(toLast: 20).observeSingleEvent(of: .value) { snapshot in
print(snapshot.value)
for child in snapshot.children {
print(child)
if let childSnapshot = child as? DataSnapshot {
guard let dictionary = childSnapshot.value as? [String: AnyObject] else {return}
let message = Message(dictionary: dictionary)
messages.append(message)
}
}
return completion(messages)
}
}
Just a guess but you may have a problem with your data structure.
That guard statement
guard let dictionary = childSnapshot.value as? [String: AnyObject] else {return}
will prevent the messages array from being fully populated when it fails.
My guess is your retrieving say, 10 child notes, then as the code iterates over them, at some point the guard statement fails due to the structure. For example a [Int: Any] instead of a [String: Any]
The end result is that not all of the child nodes are not added to the array - which in turn means there's less elements in the array than was was actually retrieved from Firebase.

Accessing firebase database returns nil swift

I want to access database through this code :
let ref = Database.database().reference()
ref.observeSingleEvent(of: .value, with: { (snapshot) in
let value = snapshot.value as? NSDictionary
print(value)
}) { (error) in
print(error.localizedDescription)
}
Here is my database :
The value printed is nil. I don't understand why...
What I tried :
I printed the value of the snapshot which is a dictionary.
I think the problem is casting the data as? NSDictionary
Can you try:
let value = snapshot.value as? [String:String]

Converting to Swift 4, ambiguous subscript error

I am new to swift and currently facing issue at highlighted section of code, the error is Ambiguous use of subscript. I tried other solutions I could find on stackoverflow but could not resolve. Please help me understand the error and its solution.
do{
guard let jsonData = data else {
throw MyError.FoundNil("JSON data issue!")
}
guard let dictionaryData = try? JSONSerialization.jsonObject(with: jsonData, options: .mutableContainers) as! [String:AnyObject] else {
throw MyError.SerializationError("Unable to serialize")
}
guard let city = dictionaryData["city"]!["name"]!,
// Error on next three lines
let data1 = dictionaryData["list"]![0]! as? [String: AnyObject],
let data2 = dictionaryData["list"]![1]! as? [String: AnyObject],
let data3 = dictionaryData["list"]![2]! as? [String: AnyObject],
let t1 = data1["t"] as? [String: AnyObject],
let t2 = data2["t"] as? [String: AnyObject],
let t3 = data3["t"] as? [String: AnyObject],
let wDay1 = data1["w"]![0]! as? [String:AnyObject],
let wDay2 = data2["w"]![0]! as? [String:AnyObject],
let wDay3 = data3["w"]![0]! as? [String:AnyObject]
else {
throw MyError.DataPopulateError("Mismatch in assigning values from dictionary")
}
First, do not use AnyObject. Define your dictionary as [String: Any].
Next, the problem is once you do something like dictionaryData["some key"] you now have an Any. That needs to be cast to do anything further with it. The error is from trying to use array index access on an Any.
Last, you are misusing the ! operator. The whole point of a guard let is to safely unwrap and safely cast a value. You defeat the whole point by using ! which will crash your app if the data isn't what your code assumes it is.
Update the 2nd guard as:
guard let dictionaryData = try? JSONSerialization.jsonObject(with: jsonData, options: []) as! [String:Any] else {
throw MyError.SerializationError("Unable to serialize")
}
Then rewrite your big guard as follows:
guard let city = (dictionaryData["city"] as? [String:Any])?["name"] as? String,
let list = dictionaryData["list"] as? [[String:Any]], list.count >= 3,
let t1 = list[0]["t"] as? [String:Any],
let t2 = list[1]["t"] as? [String:Any],
let t3 = list[2]["t"] as? [String:Any],
let wDay1 = (list[0]["w"] as? [[String:Any]])?.first,
let wDay2 = (list[1]["w"] as? [[String:Any]])?.first,
let wDay3 = (list[2]["w"] as? [[String:Any]])?.first
else {
throw MyError.DataPopulateError("Mismatch in assigning values from dictionary")
}

Fetch a specific value from Firebase

I want to be able to get the address and name of the users in firebase, but I just can't find a way to do it.
Here is my best effort. This seems fine in Xcode, but the app crashes when I push the button to retrieve the values ( thread 1 exc_bad_instruction (code=exc_i386_invop subcode=0x0)
ref?.child("users").child(user)
.observeSingleEvent(of: .value, with: { (snapshot) in
let userDict = snapshot.value as! [String: Any]
let address = userDict["Address:"] as! String
let name = userDict["Name:"] as! String
print("Address: \(address) Name: \(name)")})
like #Moritz mentioned in the comment, if you force unwrap (you are telling these values won't be nil) and if one of your values turn out to be nil, it will crash the app. Try something like this -
ref?.child("users").child(user).observeSingleEvent(of: .value, with: { snapshot in
guard let userDict = snapshot.value as? [String: Any],
let address = userDict["Address:"] as? String,
let name = userDict["Name:"] as? String else {
return
}
print("Address: \(address) Name: \(name)")
})
This will not print anything if either of your Name or Address is nil

Error while parsing Json in swift 2.3

I am trying to parse this NSDictionary
{"fare":{"value":99.03,"fare_id":"12313545861568689494880005558558852","expires_at":1485864494,"display":"\u20b999.03","currency_code":"INR"},"trip":{"distance_unit":"mile","duration_estimate":720,"distance_estimate":2.76},"pickup_estimate":2}
My code is:
if let statusesArray = try? NSJSONSerialization.JSONObjectWithData(data!, options: []) as? [[String: Any]],
let user = statusesArray![0]["fare"] as? [String: Any],
let username = user["fare_id"] as? String {
// Finally we got the username
}
else
{
print("DONE")
}
But I am not getting the value fare ID. In fact its printing "DONE" from the else statement. I tried using apple's documentation of handling data,But the same error persist.
Your JSON response is Dictionary not Array, so type cast it to [String:AnyObject] and then get fare_id from the nested fare Dictionary.
if let dict = (try? NSJSONSerialization.JSONObjectWithData(data!, options: [])) as? [String: AnyObject],
let fareDict = dict["fare"] as? [String:AnyObject]
let username = fareDict["fare_id"] as? String {
print(username)
}