Retrieve values from within autoID node - swift

I would like to get the values from within a autoID node. Below is my structure:
"workout"
"exercise"
"Bench Press"
"(AutoIDNode)"
"reps: 10"
"set: 1"
"weight: 60"
How can I get the values of "reps", "set" and "weight".
Here is my swift code:
refSets.child("workout").child("exercise").child("Bench Press").observe(DataEventType.value, with: {(snapshot) in
if snapshot.childrenCount > 0 {
self.setsData.removeAll()
for sets in snapshot.children {
let snap = sets as! DataSnapshot
let key = snap.key
let value = snap.value
print(key)
print(value!)
}
}
})
I am aware I am missing the .child() path for the autoID node following .child("Bench Press"). How can I access this node?
Thanks in advance

You can try
refSets.child("workout").child("exercise").child("Bench Press").observeSingleEvent(of: .value, with: {(snapshot) in
if let res = snapshot.value as? [String:[String:Int]] {
for item in Array(res.values) {
print(item["reps"])
}
}
})

What about that?
refSets
.child("workout")
.child("exercise")
.child("Bench Press").observe(.value, with: {(snapshot) in
guard let values = snapshot.value as [String: Any] else {
return
}
for (key, value) in values {
guard let objDict = value as? [String: Any],
let reps = objDict["reps"] as? Double /*not sure maybe Int*/,
let set = objDict["set"] as? Double,
let weight = objDict["weight"] as? Double else {
continue
}
let bp = BenchPress(reps: reps, set: set, weight: weight)
}
})
struct BenchPress {
private let reps: Double
private let set: Double
private let weight: Double
init(reps: Double, set: Double, weight: Double) {
self.reps = reps
self.set = set
self.weight = weight
}
}

Related

How to retrieve data from firebase and show particular data?

I am setting a function that allows the user to retrieve data that they have store inside the database. When user types in the value of data, it checks and displays the data to user when the is information already stored in the database. How can I retrieve the data by search 'icNumber' and display all the data that under that child value?
Here’s a screenshot of what I am trying to achieve.
Lastly, here’s my code
func displayRecord() {
//guard let uid = Auth.auth().currentUser?.uid else { return }
Database.database().reference().child("Patient_Data").observeSingleEvent(of: .value) { (snapshot) in
guard let name = snapshot.value as? String else { return }
guard let icNumber = snapshot.value as? String else { return }
guard let gender = snapshot.value as? String else { return }
guard let phoneNumber = snapshot.value as? String else { return }
guard let medicationAllergic = snapshot.value as? String else { return }
guard let smokerRecord = snapshot.value as? String else { return }
self.welcomeLabel.text = "Name, \(name)"
self.welcomeLabel.text = "IC Number, \(icNumber)"
self.welcomeLabel.text = "Gender, \(gender)"
self.welcomeLabel.text = "Phone Number, \(phoneNumber)"
self.welcomeLabel.text = "Medication Allergic, \(medicationAllergic)"
self.welcomeLabel.text = "Smoker Record, \(smokerRecord)"
UIView.animate(withDuration: 0.5, animations: {
self.welcomeLabel.alpha = 1
})
}
}
You probably want to change your displayRecord method to take an entry id ("-Lq_y67Rndy3BLyaKA7Q") so you see only one entry at a time, instead of every patients' data in your system. Then, you need to cast your snapshot value to a dictionary that matches the types stored on your database. That is the guard let dict = snapshot.value as? [String:String] else { return } line.
func displayRecord(entryId: String) {
Database.database().reference().child("Patient_Data/\(entryId)").observeSingleEvent(of: .value) { (snapshot) in
guard let dict = snapshot.value as? [String:String] else { return }
let name = dict["name"]
let icNumber = dict["icNumber"]
let gender = dict["gender"]
let phoneNumber = dict["phoneNumber"]
let medicationAllergic = dict["medicationAllergic"]
self.welcomeLabel.text = "Name, \(name)"
self.welcomeLabel.text = "IC Number, \(icNumber)"
self.welcomeLabel.text = "Gender, \(gender)"
self.welcomeLabel.text = "Phone Number, \(phoneNumber)"
self.welcomeLabel.text = "Medication Allergic, \(medicationAllergic)"
self.welcomeLabel.text = "Smoker Record, \(smokerRecord)"
UIView.animate(withDuration: 0.5, animations: {
self.welcomeLabel.alpha = 1
})
}
}
It seems that you think that your snapshot's value will be of type String. This must be why you are casting the value as string, and to multiple properties (it makes no sense to do this, even if your snapshot value was a string).
You may also want to consider whether all of these values should be stored as Strings on your backend.

Can't get node of firebase children

Hi there i'm newest in swift. I am working with a firebase database with at 2 layer of hierarchy as well as many children for each node. I got 1st layer (descript, enddata and other), but i stll can't get the news node. Is in 3 to 5 random keys. I sow many issues but still not have issue for me.
I'm understand i'm doing some wrong but what?
The Firebase is:
i need retreat the news child
struct is
struct ICONews {
let ICOId: String
let news1: String
let news2: String
let news3: String
init?(ICOId: String, dict: [String: Any] ) {
self.ICOId=ICOId
guard let news1 = dict[""] as? String,
let news2 = dict[""] as? String,
let news3 = dict[""] as? String
else { return nil }
self.news1 = news1
self.news2 = news2
self.news3 = news3
}
}
struct NewsSnapShot {
let posts: [ICONews]
init?(with snapshot: DataSnapshot) {
var posts = [ICONews] ()
guard let snapDict = snapshot.value as? [String: [String: Any]] else { return nil }
for snap in snapDict {
guard let post = ICONews (ICOId: snap.key, dict: snap.value) else {continue}
posts.append(post)
}
self.posts=posts
}
}
class of DataBase
class DatabaseService {
static let shared = DatabaseService()
private init(){}
let ICOReference = Database.database().reference()
}
and retreat method
DatabaseService.shared.ICOReference.child("news").observe(DataEventType.value, with: { (snapshot) in
guard let postsSnapShot = ICOSnapShot(with: snapshot) else {return}
})
done
Database.database().reference().observeSingleEvent(of: .value, with: {(snapshot) in
let enumerator = snapshot.children
while let rest = enumerator.nextObject() as? DataSnapshot {
let values = (rest as! DataSnapshot).value as? NSDictionary
let enumeratorMap1 = (rest as! DataSnapshot).children
while let rest2 = enumeratorMap1.nextObject() as? DataSnapshot {
let valuesMap1 = (rest2 as! DataSnapshot).value as? NSDictionary
if (rest2 as! DataSnapshot).key == "news" {
print(rest2.value)
}
}
}
})
Make the the Firebase Api call like
Database.database().reference().child("users").child(userID).observe(.childAdded, with: { (snapshot) in
if snapshot.exists() {
let receivedMessage = snapshot.value as! [String: Any]
let name = receivedMessage["name"] as? String ?? ""
let id = receivedMessage["id"] as? Double ?? 0.0
let profileurl = receivedMessage["url"] as? String ?? ""
completion(User(name: name, id: id, url: url))
} else {
failure()
}
})

Accessing data inside a closure after it has been completed

I want to be able to access the results array, after all the data has been added from Firebase to my array. Every time I try this, I get nil array.
Objective is to have a list of location info objects in an array, loaded through Firebase.
My code snippet:
class func loadData(){
let root = FIRDatabase.database().reference()
let locationSummary = root.child("LocSummary")
locationSummary.observe(.childAdded,with: { (snapshot) in
print("inside closure")
let values = snapshot.value as? NSDictionary
let name = values?["Name"] as? String ?? ""
let rating = values?["Rating"] as? Int
let latitude = values?["Latitude"] as? Double
let longitude = values?["Longitude"] as? Double
let musicType = values?["Music"] as? String ?? ""
let loc = LocationInfo.init(name: name, rating: rating!, lat:
latitude!, long: longitude!, musicTyp: musicType)
resultsArray.append(loc)
})
}
Try something like this:
class func loadData(completion: #escaping (_ location: LocationInfo) -> Void) {
let root = FIRDatabase.database().reference()
let locationSummary = root.child("LocSummary")
locationSummary.observe(.childAdded,with: { (snapshot) in
print("inside closure")
let values = snapshot.value as? NSDictionary
let name = values?["Name"] as? String ?? ""
let rating = values?["Rating"] as? Int
let latitude = values?["Latitude"] as? Double
let longitude = values?["Longitude"] as? Double
let musicType = values?["Music"] as? String ?? ""
let loc = LocationInfo.init(name: name, rating: rating!, lat:
latitude!, long: longitude!, musicTyp: musicType)
completion(loc)
})
}
In your cycle add something like this:
func getArray(completion: #escaping (_ yourArray: [LocationInfo]) -> Void {
var resultsArray = [LocationInfo]()
let countOfLoadedItems = 0
for item in yourArrayForCycle { // or your own cycle. Implement your logic
loadData(completion: { location in
countOfLoadedItems += 1
resultsArray.append(location)
if countOfLoadedItems == yourArrayForCycle.count {
completion(resultsArray)
}
})
}
}
Then in function, where you wants your data:
getArray(completion: { result in
yourArrayToFill = result
// reload data etc..
})
Something like this. Adapt it to your solution.
Hope it helps

facing Issue in parsing in swift3

I am trying to parse the emergency data in into emergency struct but it never statifies the condition and get into else case.Here is my code and structure.Some thing i have written woring in first line.
if let emergencyDict = snapshotValue["emergency"] as? [String:[String:Any]]{
for (emerId, emerData) in emergencyDict {
let emer = Emergency.init(emergency: emerData as NSDictionary)
emergency.append(emer)
}
}
else{
let emer = Emergency.init(emerg: "" as AnyObject)
emergency.append(emer)
}
struct Emergency{
var emer_id: String
var emer_name: String
var emer_phoneNo: String
init(emergency: NSDictionary) {
if emergency.object(forKey: "id") != nil {
emer_id = emergency.object(forKey: "id") as! String
}
else{
emer_id = ""
}
}
}
The problem you are having emergency as Array with type [Any] and if you remove the first object then you get Array of type [[String:Any]]. So try like this way.
if let array = snapshotValue["emergency"] as? [Any],
let emergencyArrar = Array(array.dropFirst()) as? [[String:Any]] {
print(emergencyArray)
for emergency in emergencyArray {
print(emergency)
}
}
You have written wrong in this line:
if let emergencyDict = snapshotValue["emergency"] as? [String:[String:Any]]{
It should be:
if let emergencyDict = snapshotValue["emergency"] as? [[String:Any]]{
This question should belong to query from firebase database.
// you have to get the children in emergency,
// then get the value(dictionary) of each child
ref.child("emergency").observeSingleEvent(of: .value, with: { (snapshot) in
let value = snapshot.value as? NSDictionary
let keys = value?.allKeys // [1, 2, 3 ....]
for key in keys {
ref.child("emergency").child(key)..observeSingleEvent(of: .value, with: { (snapshot) in
let value = snapshot.value as? NSDictionary
// Here is your dictionary
}
}
}) { (error) in
print(error.localizedDescription)
}

possible to cast this Alamofire result to an array of dictionaries

I am not an iOS dev and have to make a few changes to a Swift / AlamoFire project (not mine) and am a bit lost.
I have the following JSON:
{"metro_locations":
[
{
"name":"Ruby Red"
},
{
"name":"Blue Ocean"
}
]
}
class (I know that there are issues here):
class Location{
var name=""
init(obj:tmp){
self.name=tmp["name"]
}
}
and need to make an AlamoFire call
Alamofire.request(.GET, "https://www.domain.com/arc/v1/api/metro_areas/1", parameters: nil)
.responseJSON { response in
if let dataFromNetworking = response.result.value {
let metroLocations = dataFromNetworking["metro_locations"]
var locations: [Location]=[]
for tmp in metroLocations as! [Dictionary] { // <- not working, Generic Paramter 'Key' could not be inferred
let location=Location.init(obj: tmp)
locations.append(location)
}
}
}
I have included the error msg, the "not working" but feel that there are issues in other parts too (like expecting a dictionary in the initialization). What does the 'Key' could not be inferred mean and are there other changes I need to make?
edit #1
I have updated my Location to this to reflect your suggestion:
init?(dictionary: [String: AnyObject]) {
guard let id = dictionary["id"] else { return nil }
guard let name = dictionary["name"] else { return nil }
guard let latitude = dictionary["latitude"] else { return nil }
guard let longitude = dictionary["longitude"] else { return nil }
self.name = name as! String
self.id = id as! Int
self.latitude = latitude as! Double
self.longitude = longitude as! Double
}
but I get the error:
Could not cast value of type 'NSNull' (0x10f387600) to 'NSNumber' (0x10f77f2a0).
like this:
I would think that the guard statement would prevent this. What am I missing?
You can cast metroLocations as an array of dictionaries, namely:
Array<Dictionary<String, String>>
Or, more concisely:
[[String: String]]
Thus:
if let dataFromNetworking = response.result.value {
guard let metroLocations = dataFromNetworking["metro_locations"] as? [[String: String]] else {
print("this was not an array of dictionaries where the values were all strings")
return
}
var locations = [Location]()
for dictionary in metroLocations {
if let location = Location(dictionary: dictionary) {
locations.append(location)
}
}
}
Where
class Location {
let name: String
init?(dictionary: [String: String]) {
guard let name = dictionary["name"] else { return nil }
self.name = name
}
}
Clearly, I used [[String: String]] to represent an array of dictionaries where the values were all strings, as in your example. If the values included objects other than strings (numbers, booleans, etc.), then you might use [[String: AnyObject]].
In your revision, you show us a more complete Location implementation. You should avoid as! forced casting, and instead us as? in the guard statements:
class Location {
let id: Int
let name: String
let latitude: Double
let longitude: Double
init?(dictionary: [String: AnyObject]) {
guard let id = dictionary["id"] as? Int,
let name = dictionary["name"] as? String,
let latitude = dictionary["latitude"] as? Double,
let longitude = dictionary["longitude"] as? Double else {
return nil
}
self.name = name
self.id = id
self.latitude = latitude
self.longitude = longitude
}
}