Downloading Rating from firebase, first rating always shows up as nan - swift

So I'm trying to download the ratings from firebase database and then show them on a Mapbox subtitle. however the first and only the first infographic shows up as nan.
Ive tried dispatches and times, and unfortunately nothing seems to be working. I have no clue what to do.
func showCarIcon() {
ref = Database.database().reference()
ref.child("location").observe(.childAdded) { (snapshot:DataSnapshot) in
if let dict = snapshot.value as? [String:AnyObject] {
if dict["Activity"] as! String == "Car" {
let longitude = dict["Longitude"] as! String
let lattitude = dict["Lattitude"] as! String
let title = dict["Title"] as! String
let key = dict["id"] as! String
self.carIconArray.insert(coordinate(title: title, carLat: lattitude, carLng: longitude, idKey: key), at: 0)
let n = self.carIconArray.count
for carMarker in 1...n {
let location = CLLocationCoordinate2D(latitude: Double(lattitude)!, longitude: Double(longitude)!)
let carMarker = CustomPointAnnotation(coordinate: location)
var totalrating = Double(0)
var ratingcount = Double(0)
self.ref.child("location/\(key)/Ratings").observe(.value, with: { (snapshot: DataSnapshot) in
for childSnap in snapshot.children.allObjects {
let snap = childSnap as! DataSnapshot
let rating = snap.value as! Double
totalrating += rating
ratingcount += 1
}
let netRating = Double(totalrating/ratingcount)
let final = Double(round(100*netRating)/100)
carMarker.reuseIdentifier = "carMarker"
carMarker.image = UIImage(named: "carPin")
carMarker.title = title
carMarker.subtitle = "\(final)/5.0"
carMarker.key = key
// add Car marke to array
self.arrCarMarkers.append(carMarker)
// add array to map
self.mapView.addAnnotations(self.arrCarMarkers)
})
}
}
}
}
}
JSON Tree
"location" : {
"-LkKU4hLZQfI2XDdljQk-LkKU9ZkGYnP82pKeZoe-LkKUD50ouEXYT9LuzSw" : {
"Activity" : "Car",
"Coordinate" : "-35.13815006034659,138.53838695658027",
"Description" : "H",
"Difficulty" : "Medium",
"Lattitude" : "-35.13815006034659",
"Longitude" : "138.53838695658027",
"Ratings" : {
"WgPMwulBX9ScTHqa0htPyr355TQ2" : 4
"Bfodb4309gn30fnofjlnd3u93438" : 5
},
"Title" : "H",
"id" : "-LkKUD50ouEXYT9LuzSw",
}
}
Please can someone help me!!

Related

Fetch multi level node from Firebase

I am trying to fetch the "friends" from the node to be able to show them in UICollectionView afterwards. I now realized that I have to use a struct and place the Friends array inside. I am struggling now to understand how to fetch them into that array (you can see it at the bottom of the post). Data is stored in a firebase node. How can I grab the data and what would be the procedure to place it in UICollectionView afterwards? This is my function so far to retrieve.
UPDATE: (I think I am fetching correctly now but I don't get any results. Is there something that I should do in collection view? or what am I doing wrong?)
UPDATE: Here is my code for post fetching:
func fetchPosts3() {
ref.child("Users_Posts").child("\(unique)").queryOrderedByKey().observeSingleEvent(of: .value, with: { snapshot in
print(snapshot)
if snapshot.value as? [String : AnyObject] != nil {
let allPosts = snapshot.value as! [String : AnyObject]
self.posts.removeAll()
for (_, value) in allPosts {
if let postID = value["postID"] as? String,
let userIDDD = value["userID"] as? String
{
//ACCESS FRIENDS
ref.child("Users_Posts").child("\(unique)").child(postID).child("friends").queryOrderedByKey().observeSingleEvent(of: .value, with: { (snap) in
print("FRIENDS: \(snap.childrenCount)")
//var routine = self.postsWithFriends[0].friends
for friendSnap in snap.children {
if let friendSnapshot = friendSnap as? DataSnapshot {
let friendDict = friendSnapshot.value as? [String: Any]
let friendName = friendDict?["name"] as? String
let friendPostID = friendDict?["postID"] as? String
let postsToShow = PostWithFriends(id: userIDDD, friends: [Friend(friendName: friendName!, friendPostID: friendPostID!)])
self.postsWithFriends.append(postsToShow)
print("COUNTING: \(self.postsWithFriends.count)")
// then do whatever you need with your friendOnPost
}
}
})
}
}
//GET LOCATION
self.collectionView?.reloadData()
self.posts.sort(by: {$0.intervalPosts! > $1.intervalPosts!})
}
})
ref.removeAllObservers()
}
That's how the data looks at the database:
{
"-LN2rl2414KAISO_qcK_" : {
"cellID" : "2",
"city" : "Reading",
"date" : "2018-09-23 00:41:26 +0000",
"friends" : {
"UJDB35HDTIdssCtZfEsMbDDmBYw2" : {
"name" : "Natalia",
"postID" : "-LN2rl2414KAISO_qcK_",
"userID" : "UJDB35HDTIdssCtZfEsMbDDmBYw2"
},
"Vyobk7hJu5OGzOe7E1fcYTbMvVI2" : {
"name" : "Gina C",
"postID" : "-LN2rl2414KAISO_qcK_",
"userID" : "Vyobk7hJu5OGzOe7E1fcYTbMvVI2"
}
},
}
}
And this is my object that's stored into array
struct PostWithFriends {
var postID : String?
var friends: [Friend]
}
class Friend : NSObject {
var friendName: String?
var friendUserID: String?
var postID: String?
init(friendName: String, friendPostID: String) {
self.friendName = friendName
self.postID = friendPostID
}
}
Replace this
if let friend = snap.value as? [String : AnyObject] {
}
With this:
for friendSnap in snap.children {
if let friendSnapshot = friendSnap as? FIRDataSnapshot {
let friendOnPost = FriendOnPost()
let friendDict = friendSnapshot.value as? [String: Any]
friendOnPost.name = friendDict?["name"] as? String
friendOnPost.friendUserID = friendDict?["userID"] as? String
friendOnPost.postID = friendDict?["postID"] as? String
// then do whatever you need with your friendOnPost
}
}

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

i have a firebase databank looking like this(Json):
{
"user" : {
"UVHpZfD60EWcYDbeV60ENqXaioA3" : {
"email" : "thisisanothertest#gg.gg",
"location" : {
"latitude" : 37.785834,
"longitude" : -122.406417
},
"profile" : {
"alter" : "23",
"geschlecht" : "männlich",
"name" : "Mario1"
}
},
"nEsKd9uIOnSmVuMbAK0K2X1Dz6A3" : {
"email" : "thisisatest#gg.gg",
"location" : {
"latitude" : 37.785834,
"longitude" : -122.406417
},
"profile" : {
"alter" : "23",
"geschlecht" : "männlich ",
"name" : "Mario"
}
}
}
Problem:
Now i would like to get the Locations from all the users (latitude and longitude) to place them later on on a Map.
I can get the location for a single user realy easy by doing the below code. But how can i get the data from all the users at once?
var ref: DatabaseReference!
ref = Database.database().reference()
let userID = Auth.auth().currentUser?.uid
ref.child("user").child(userID!).child("location").observeSingleEvent(of: .value, with: { (snapshot) in
// Get user value
let value = snapshot.value as? NSDictionary
let lat = value?["latitude"] as? Double ?? 0.0
let long = value?["longitude"] as? Double ?? 0.0
I found a similar question already here
So i tried that code from the above link:
let usersRef = ref.child("users")
usersRef.observeSingleEvent(of: .value, with: { (snapshot) in
for snap in snapshot.children {
let userSnap = snap as! FIRDataSnapshot
let uid = userSnap.key //the uid of each user
let userDict = userSnap.value as! [String:AnyObject] //child data
let location = userDict["Location"] as! String
print("key = \(uid) is at location = \(location)")
}
})
But with that pice of code i was only able to get all the email adresses. By changing the "Location" to "email". How can i go down one more node to access the "location" node and get the latitude and longitude of all the users?
Thank you :)
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.
As you can see in your data location is stored as another object, so you have to cast it as Dictionary => [String:AnyObject]
for snap in snapshot.children {
let userSnap = snap as! FIRDataSnapshot
let uid = userSnap.key //the uid of each user
let userDict = userSnap.value as! [String:AnyObject] //child data
let location = userDict["location"] as! [String:AnyObject]
print("key = \(uid) is at location = \(location)")
}

Having trouble trying to obtain value from Firebase

I'm trying to get a value inside a Firebase database I set up but I'm having issues trying get it out. There is a section in my program where I go through each child under Cities and obtain the the name of each city. I thought it would be a good idea to try to obtain the status for each city in the same section but I can't get it out. Below is a sample of the JSON object. I feel like I'm close but missing something to put it all together.
"Users" : {
"NPNBig20BXNpX4Rz0UbMyiKAarY2" : {
"Cities" : {
"New York City" : {
"Status" : "Empty"
},
"Atlanta" : {
"Status" : "Empty"
},
"Test City" : {
"Status" : "Wow",
"Value" : "Test"
}
},
"Email" : "fakeemail#gmail.com"
}
}
Code:
guard let uid = userID else { return }
let databaseRef = Database.database().reference(fromURL: "https://testApp.firebaseio.com/").child("Users").child(uid).child("Cities")
var dataTest : [String] = []
//var cityDictionary: [String:String]()
databaseRef.observeSingleEvent(of: .value, with: {(snapshot) in
for child in snapshot.children {
let snap = child as! DataSnapshot
let key = snap.key
guard let value = snap.value else { return }
//let testData = value["Status"] **Type Any has no subscript
print("Key: ", key, "\nValue: ", value)
dataTest.append(key)
}
completion(dataTest)
})
This is the printed output
Key: New York City
Value: {
Status = Empty;
}
Key: Sintra
Value: {
Status = Empty;
}
Key: Test City
Value: {
Status = Wow;
Value = Test;
}
Here is the way you can get Status from your value:
if let value = snap.value as? [String: AnyObject] {
let Status = value["Status"] as? String ?? ""
}
And your complete code will be:
guard let uid = userID else { return }
let databaseRef = Database.database().reference(fromURL: "https://testApp.firebaseio.com/").child("Users").child(uid).child("Cities")
var dataTest : [String] = []
//var cityDictionary: [String:String]()
databaseRef.observeSingleEvent(of: .value, with: {(snapshot) in
for child in snapshot.children {
let snap = child as! DataSnapshot
let key = snap.key
guard let value = snap.value else { return }
//let testData = value["Status"] **Type Any has no subscript
if let value = snap.value as? [String: AnyObject] {
let Status = value["Status"] as? String ?? ""
}
print("Key: ", key, "\nValue: ", value)
dataTest.append(key)
}
completion(dataTest)
})
func handleGetCities(_ completion: #escaping ([String]) -> ()) {
guard let uid = Auth.auth().currentUser?.uid else { return }
// OR
guard let uid = userID else { return }
// THEN
var data: [String] = []
let reference = Database.database().reference()
reference.child("Users").child(uid).child("Cities").observe(.childAdded, with: { (snapshot) in
let city_name = snapshot.key
data.append(city_name)
completion(data)
}, withCancel: nil)
}

Retrieve / read data from Firebase database

I am using this code to retrieve data from a Firebase database. However, I am only able to pull one variable at a time. Can you please help me find a way to pull the others (student names, title etc.) and save them to an object arrayList?
{
"projects" : [
1, {
"answer1" : false,
"answer2" : true,
"answer3" : true,
"campus" : "Science Academy",
"category" : "LifeScience",
"question1" : "This is question 1",
"question2" : "This is question 2",
"question3" : "This is question 3",
"student1" : "john",
"student2" : "Kyle",
"title" : "Amazon Forest"
}
]
}
var ref : DatabaseReference?
var handle : DatabaseHandle?
ref = Database.database().reference()
handle = ref?.child("projects").child("1").child(question1).observe(.value, with: { (snapshot) in
if let question = snapshot.value as? String {
print(question)
}
})
IF your database has more that just projects/1 and you're wanting to access projects/1-2-3-4 etc. then you'll want to do something like this:
let reference = Database.database().reference()
reference.child("projects").observe(.childAdded, with: { (snapshot) in
let key = snapshot.key // THIS WILL GET THE PROJECT THAT IT'S IN. 1, 2, 3, 4 etc.
guard let dictionary = snapshot.value as? [String: AnyObject] else { return }
let answer1 = dictionary["answer1"] as? Bool
let campus = dictionary["campus"] as? String
}, withCancel: nil)
IF you're wanting to simple get a hold of all the values inside of project/1 and not just the questions, you'll want to do something like this:
let reference = Database.database().reference()
reference.child("projects").child("1").observeSingleEvent(of: .value, with: { (snapshot) in
let key = snapshot.key // THIS WILL GET THE PROJECT THAT IT'S IN. 1, 2, 3, 4 etc.
guard let dictionary = snapshot.value as? [String: AnyObject] else { return }
let answer1 = dictionary["answer1"] as? Bool
let campus = dictionary["campus"] as? String
}, withCancel: nil)

Filter Firebase data Swift

I want to load every image of type Modern on Firebase with Swift. How can I do it?
Here's my data model:
"arts" : {
"-KW5plrmDFMGa9pUlTg3" : {
"description" : "Title ",
"height" : 25.36023,
"imageUrl" : "https://firebasestorage.googleapis.com/v0/b/medici-b6f69.appspot.com/o/Arts%2FJ7U039FN6YckdbQ7KgeJKuZDO2I3%2F26DDC192-C081-4588-BD52-2841FA3EF507?alt=media&token=e828936c-5341-4429-94e9-c3aefa81769b",
"postDate" : 1478657252917,
"title" : "Title ",
"type" : "Modern",
"width" : 25.99424
}
Here's what I tried. But it's not working.
DataBase.child("arts").queryOrdered(byChild: "Modern").observe(.value) { (snapshot: FIRDataSnapshot) in
self.posts = []
if let snapshot = snapshot.children.allObjects as? [FIRDataSnapshot] {
print("SNAPSHOT: \(snapshot)")
for snap in snapshot {
if let postDict = snap.value as? Dictionary<String, AnyObject> {
let key = snap.key
let post = ProfileArtModel(key: key, artData: postDict)
self.posts.insert(post, at: 0)
}
}
}
self.tableView.reloadData()
}
Try:-
DataBase.child("arts").queryOrdered(byChild: "type").queryEqual(toValue : "Modern").observe(.value) { (snapshot: FIRDataSnapshot) in
self.posts = []
if let snapshot = snapshot.children.allObjects as? [FIRDataSnapshot] {
print("SNAPSHOT: \(snapshot)")
for snap in snapshot {
if let postDict = snap.value as? Dictionary<String, AnyObject> {
let key = snap.key
let post = ProfileArtModel(key: key, artData: postDict)
self.posts.insert(post, at: 0)
self.tableView.reloadData()
}
}
}
}
Your queryOrdered is in wrong format. Also you are always inserting an object into your self.posts array at 0 index, so your array is always replacing an object of 0 position. So you can modify your code as below:
self.posts = []
DataBase.child("arts").queryOrdered(byChild: "type").queryEqual(toValue : "Modern").observe(.value) { (snapshot: FIRDataSnapshot) in
if let snapshot = snapshot.children.allObjects as? [FIRDataSnapshot] {
print("SNAPSHOT: \(snapshot)")
for snap in snapshot {
if let postDict = snap.value as? Dictionary<String, AnyObject> {
let key = snap.key
let post = ProfileArtModel(key: key, artData: postDict)
self.posts.append(post)
}
}
self.tableView.reloadData()
}
}