Decoding JSON in Swift - ios

I am fetching JSON data from my server. I am using Alamofire in my code to fetch data from server.
Here's how I am decoding it:
Alamofire.request(URL_GET_DATA, method: .post).responseJSON { response in
//getting json
if let json = response.result.value {
print(json)
let newsJson : NSArray = json as! NSArray
self.parseData(data: ((newsJson[0] as AnyObject).value(forKey: "message") as? String)!)
}
}
func parseData(data : String){
//traversing through all elements of the array
let newsArray: NSArray = data as! NSArray
for i in 0..<newsArray.count{
//adding hero values to the hero list
self.newsList.append(Objectnews(
id : (newsArray[i] as AnyObject).value(forKey: "id") as? String,
heading: (newsArray[i] as AnyObject).value(forKey: "heading") as? String,
description : (newsArray[i] as AnyObject).value(forKey: "description") as? String,
time_stamp : (newsArray[i] as AnyObject).value(forKey: "time_stamp") as? String,
type : (newsArray[i] as AnyObject).value(forKey: "type") as? String,
imageurl: (newsArray[i] as AnyObject).value(forKey: "imageurl") as? String
))
}
print("reloading table")
//displaying data in tableview
self.tableView.reloadData()
}
Here's the log for same. It contains the response from server and the error it is throwing:
{
error = 0;
message = (
{
description = "September 5th marks Teacher\U2019s Day in India. It is celebrated on the birthday of our second President, Sarvepalli Radhakrishnan. It is a day when we pay respect to our teachers and appreciate their contribution to the society and our individual lives and plan special surprises, have a chance to thank them for their selfless work in making the leaders for tomorrow. N.S.S. unit celebrated Teacher's day by gifting a hand made card to each Teaching and Non-Teaching Staff of P.G.D.A.V. College. We will also like to put forward a special thanks to the creative department team of N.S.S. for their terrific job in making those beautiful hand made cards. Happy Teachers' Day to All!";
heading = "Teacher's Day Celebration";
id = 16;
imageurl = "http://check.png";
"time_stamp" = "05/09/2017 22:58";
type = News;
},
{
description = "Incessant rains and floods have brought a havoc in one of India's most populous state, Bihar due to which roads have been closed, houses destroyed and crores affected. Rahat - an initiative of Goonj NGO steps in such situations helping all those in need and this time NSS PGDAV is doing their share of help by donating Via GOONJ and is organising a Collection Drive for the flood survivors. Your donation will provide shelter, food and comfort to families. Below are some of the things you can donate to help the people:-\n\n-Tarpaulins\n-Old flex and ropes\n-Mosquito nets\n-Dry ration\n-Clothing\n-Good quality blankets \n-Wooden toiletries\n-Utensils \n-Bucket\n-Torch and batteries\n-Umbrella\n-Slippers\n-Candles\n-Solar lights etc\n\nGiving is not just about making a donation. It's about making a difference! So step forward and #DONATE.\n\nDate: 4th-9th September 2017.\nVenue- Lobby/Office Area.\nTime: 10AM-1PM.\n\nFor queries contact:\nEkta- 7503894368\nJhanvi- 7838401571";
heading = "Collection Drive for Flood Affected Areas";
id = 15;
imageurl = "http://check.png";
"time_stamp" = "02/09/2017 21:34";
type = News;
},
{
description = "\"Beauty isn't about having a pretty face, it is about having a pretty soul, a pretty heart and a pretty mind.\"\n\nN.S.S. P.G.D.A.V. is honoured and takes a great pride in telling that MS. LAXMI AGARWAL will be speaking at the orientation program of N.S.S. which is set to be held on 26th August from 12:00 P.M. onwards. Ms. Laxmi Agarwal has inspired this country by her courage and has been the recipient of International Women of Courage Award by Michelle Obama. She is an epitome of bravery.\n\nWe could not have been more proud and excited to have her encourage the students and motivate them to overcome barriers and achieve what they aim for. We are sure she will fill in positive vibes around the program and will inspire us all to do what we need to do, to achieve what we dream for, and to inspire others for the same.";
heading = "NSS Orientation ";
id = 14;
imageurl = "http://check.png";
"time_stamp" = "25/08/2017 16:47";
type = News;
},
{
description = "Welcome Fresher's,\nHere is the last step for final selection to become a member of N.S.S. Team.\nIt's the Personal Interview. So following is the list of students who have to appear on August 2, 2017\n\n\n\n\n\n\nDAY 1 - AUGUST 2, 2017\U00a0\nSLOT 1- 10:00 A.M. - 11:00 A.M.\n\n\nAmit\U00a0\nAditya Sapra\U00a0\nAman Gupta\U00a0\nAadesh Sachdeva\U00a0\nAkshay Gaba\U00a0\nAkansha Sharma\U00a0\nAnjali Kataria\U00a0\nAakash\U00a0\nAbhinav Kumar Malviya\U00a0\nAnkita Rai\U00a0\nAstha Kanojia\U00a0\nAnita Mandal\U00a0\nAnchal\U00a0\nArif\U00a0\nAaftab Ahmad\U00a0\nAshish\U00a0\nAashirya Mittal\U00a0\nAnshul Saini\U00a0\nAnanya Singh\U00a0\nAbhay Goyal\U00a0\nAnshu Kumari Gupta\U00a0\nAjay Kumar\U00a0\nAaftab\U00a0\nAnjali Bhatt\U00a0\nAditi Singh\U00a0\nAnirudh Ahlawat\U00a0\nAshutosh\U00a0\nAnuradha\U00a0\nAmiza\U00a0\nAsmat Khan\U00a0\nAyushi Chadha\U00a0\nAmbujakshi Bhardwaj\U00a0\nAnubhav jain\U00a0\nAshutosh Verma\U00a0\nAbhishek Anand\U00a0\nAbhiraj\U00a0\nAkansha\U00a0\nAbhishek ranjan\U00a0\nAyesha Chauhan\U00a0\nAkansha\U00a0\n\n\nSLOT 2 - 11:00 A.M. - 12:00 P.M.\n\n\nAnkit\U00a0\nAmar Jeet Verma\U00a0\nAnshika Adlakha\U00a0\nAnkur Verma\U00a0\nAnkita\U00a0\nAditya Raj Chaudhary\U00a0\nBhavay Virmani\U00a0\nBunty Kumar\U00a0\nBhawna\U00a0\nBronika Paul\U00a0\nBarkat Ali\U00a0\nBrahmadutt\U00a0\nBadal Sharma\U00a0\nBhavnish Sharma\U00a0\nChandra Prakash Bhambhu\U00a0\nChanchal\U00a0\nChetna Garg\U00a0\nChetan Verma\U00a0\nChirag Sethi\U00a0\nChetan\U00a0\nDeependra Pal Yadav\U00a0\nDivya Agnihotri\U00a0\nDeepak Sahni\U00a0\nDrishya Wahil\U00a0\nDiksha paut\U00a0\nDevendra Yadav\U00a0\nDivya Chabra\U00a0\nDeep Singh\U00a0\nDeepankar Vaid\U00a0\nDrishti Goyal\U00a0\nEkta Shankar\U00a0\nFarzan Iqram\U00a0\nGaurav Bhatt\U00a0\nGarima Behl\U00a0\nGaurav Saini\U00a0\nGarvish Nanda\U00a0\nGaurav Kumar\U00a0\nGarima Payla\U00a0\nGauri Dhamija\U00a0\nharshit Singh\U00a0\n\n\nSLOT 3 - 12:00 P.M. - 1:00 P.M.\n\n\U00a0\U00a0\nHimanshi Sharma\U00a0\nHarsh Gupta\U00a0\nHarshit Girdhar\U00a0\nHarsh Bansal\U00a0\nHarshita Chauhan\U00a0\nHeena\U00a0\nHeena\U00a0\nIrfan Khan\U00a0\nIshu Rai\U00a0\nJaspreet kaur\U00a0\nJyoti\U00a0\nJaisny\U00a0\nJyoti Nishad\U00a0\nKrishan Kumar\U00a0\nKrishna\U00a0\nKetu\U00a0\nKrishika Arora\U00a0\nKhushboo Yadav\U00a0\nKanan Makker\U00a0\nKriti Kapoor\U00a0\nKanika Yadav\U00a0\nKiran Pachori\U00a0\nKunal Nagar\U00a0\nKhushboo Bansal\U00a0\nKunal Sharma\U00a0\nKajal\U00a0\nLalit Mohan\U00a0\nLovely Mathur\U00a0\nMitali Baisoya\U00a0\nmanisha\U00a0\nMiti Dangwal\U00a0\nMukul Puri\U00a0\nMansingh\U00a0\nManoj Meena\U00a0\nMohammad faisal\U00a0\nM. Danish Ameer\U00a0\nMohit Jain\U00a0\nMantu Babu\U00a0";
heading = "NSS Interview Day 1";
id = 13;
imageurl = "http://check.png";
"time_stamp" = "01/08/2017 22:30";
type = News;
},
{
description = "Time and tide waits for none, we all learnt this proverb in our primary school but yesterday I experienced something contradictory to my learning. I saw the time stopping and taking a moment to absorb what was happening around? And guess what was it, it was you, the participants, the audience of Sevaarth whose overwhelming response took the event to a whole new level. You made the mighty time get adrenaline rush. \nThis year we brought in many technical advancement to our NSS unit. We launched our mobile app, website. We facilitated user with many problem solving features. We had more number of volunteers than previous year. Our reach set a new record in the history of all NSS Unit with a growth rate of more than 17,000%. As Sevaarth '17 ended in a great way, we are much more inspired by the work of every people who put their day and night in making sure you get what we have to offer. We are humbled by the response of people. \nWe owe a great deal to our sponsers - Little App, PaisaWapas, DCOP, DSB, Internsala, Nestle, SelfDrives.in, CareerLauncher, Student Stories, The Education Tree, DU Beat, Drama Cafe. Thank you to all.\nWe have a aim. We have people who craves great passion. And, these two thing is advancing us to a new level each and every day. Every day, NSS puts a positive value in this society. We are here to make a better world for each and every person out there. No matter what's your race, nationality, religion, we will make sure that you get what you deserve. In the coming years, NSS Unit of P.G.D.A.V College will get into different areas of society from education to better health care by acting as a bridge by them. \nSevaarth is an opportunity to showcase the talent of people who choose stay away from limelight in front of people. Sevaarth seemed to have touched its highest point with all the fun, the immense hard work, representing our culture from a different perspective. \nWe promise to bring you a more vibrant version of Sevaarth next year. Adios! ";
heading = "Thank you";
id = 12;
imageurl = "http://check.png";
"time_stamp" = "22/01/2017 00:22";
type = News;
}
);
}
Could not cast value of type '__NSDictionaryI' (0x106456288) to 'NSArray' (0x106455e28).
(lldb)
How can I properly decode it based on the error in the log? I am using Swift.

Follow this step :
Creat a class called APIManager
Create Delegates method like this
//MARK : Custom Protocol Methods protocol
apiManagerDelegate:NSObjectProtocol {
func apiSuccessResponse(_ response: Dictionary<String, AnyObject>)
func APIFailureResponse(_ msgError: String)
}
//MARK : Custom Extension Methods
extension apiManagerDelegate {
func apiSuccessResponse(_ response: Dictionary<String, AnyObject>){
// leaving this empty
}
func APIFailureResponse(_ msgError: String){
// leaving this empty
} }
In Your View Controller , Conforms this Delegate Methods .
Defined method like this to consume web service in API Manager
func signUpAPI(firstName : String, lastName:String, email:String, password:String, confirmPwd:String, mobile:String, age:String, gender:String, signUp_type:Int) {
//Payload Dict
let payloadDict = [
"first_name" : firstName,
"last_name" : lastName,
"email" : email,
....
] as [String : Any]
//Showing activity indicator
---progressbar goes here
//Call Web API using Alamofire library
AlamoFireSharedManagerInit()
Alamofire.request(HCConstants.URL.HC_BASEURL + HCConstants.URL.SIGNUP, method: .post, parameters: payloadDict, encoding: JSONEncoding.default, headers: nil).responseJSON { response in
do
{
//Checking For Error
if let error = response.result.error {
//Call failure delegate method
print(error)
//Stop AcitivityIndicator
self.hideHud()
self.delegate?.APIFailureResponse("Something goes wrong , Try after some time!!")
return
}
//Store Response
let responseValue = try JSONSerialization.jsonObject(with: response.data!, options: JSONSerialization.ReadingOptions()) as! Dictionary<String, AnyObject>
print(responseValue)
//Check Success Flag
print(responseValue["success"] as! Bool)
if let mSuccessFlag = responseValue["success"] as? Bool {
//Failure message
if !mSuccessFlag {
self.delegate?.APIFailureResponse(responseValue["message"] as! String? ?? "Something goes wrong , Please try after some time")
}
//Call success delegate method
else {
self.delegate?.apiSuccessResponse(responseValue)
}
}
//Stop AcitivityIndicator
self.hideHud()
} catch {print("Sign up API fired exception")}
}
}
Above method parse the data and send it to the success or failure method to your viewcontroller and from there you need to populate the data and just render it .
Isn't it super easy ?

Related

Can Locale identify country by currency code?

I was looking for that answer in here, and also on official documentation, but I can't find the answer for that. I've got currency codes (e.g. "EUR"). I need to get country code (e.g "EU"). So I've seen that I can do it inversely (getting currency code by using country code), but I was trying to change this solution for my needs, and I got nil as result. Also I know I can use simple solution - remove last letter from currency code to get country code (It works for most cases from my API data, but not everywhere) - but I feel this approach is not safe. So my question is like in title: Can I identify country from currency code by using Locale?
Here is my approach:
with NSLocale
extension NSLocale {
static func currencySymbolFromCode(code: String) -> String? {
let localeIdentifier = NSLocale.localeIdentifier(fromComponents: [NSLocale.Key.currencyCode.rawValue : code])
let locale = NSLocale(localeIdentifier: localeIdentifier)
return locale.object(forKey: NSLocale.Key.countryCode) as? String
}
}
with Locale
extension Locale {
static let countryCode: [String: String] = Locale.isoCurrencyCodes.reduce(into: [:]) {
let locale = Locale(identifier: Locale.identifier(fromComponents: [NSLocale.Key.currencyCode.rawValue: $1]))
$0[$1] = (locale.regionCode)
}
}
A currency can be associated with multiple countries, you should create your own custom data implementation, such as following json
{
"EUR":"PL",
"USD":"CA"
}
Create a file in your Xcode project and name it for e.g. data.json, and paste such JSON as above, finally use following method
func getCountryCode(currency: String) -> String? {
var countryCode: String?
let url = Bundle.main.url(forResource: "data", withExtension: "json")!
do {
let data = try Data(contentsOf: url)
let json = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [String: String]
countryCode = json?[currency]
} catch {
print(error.localizedDescription)
}
return countryCode
}
Usage
if let countryCode = getCountryCode(currency: "EUR") {
print(countryCode)
}
The answer from #AamirR is a bit not accurate.
EUR != PL, PL = PLN = Poland
USD != CA, CA = CAD = Canada
In majority of cases (with some exceptions), first 2 letters of currency code = ISO 3166-2 country code:
PLN = PL = Poland
GBP = GB = Great Britain
USD = US = United States of America
AMD = AM = Armenia
CZK = CZ = Czech Republic
BRL = BR = Brazilia
and so on ...
So if you have currency codes you can get country names (with 99% accuracy) as follows:
let currencyCode = "USD"
let countryCode = String(currencyCode.prefix(2))
let countryName = Locale.current.localizedString(forRegionCode: countryCode)
print(countryName)
Optional("United States")
However, as some commented above, EU for example, is not a country, and looks like in your specific case you do not need a country flag, you need "currency flag", so for EUR you will display EU flag, which is correct, as you cant determine which EU country flag to display - France, Germany, etc ... so this approach might work for mapping currencies to countries flags.
Though there are some exceptions, in terms of first 2 letters of currency code not matching first 2 letters of country name, from ISO 3166-2 country code perspective, they still match:
CHF = CH = Switzerland
HRK = HR = Croatia
DKK = DK = Denmark
... and so on
The other interesting pattern is that first 2 letters of currency codes, would usually match country internet domain, but again, there are some exceptions from this too.

Firebase is storing value even when user deleted it

I am struggling with the problem of storing the data. I am writing app that uses the firebase for authentication and as the database. The application works as scooter sharing. When user taps on one of the markers and taps on reserve button scooter is reserved by sending string value. It goes something like this:
I am tapping on reserve button
I am sendnig check value and user ID to selected scooter record as userKey
I am waiting for server response (feedback)
If there is response start reservation
If user change their mind and click on cancel button I am clearing the userKey and changing the status from Reserved to Off.
And there is a problem.
Even when I clear the userKey in appropriate scooter the function responsible for reservation can be still executed. For example when I simulate the server and I send feedback command to previously reserved scooter below code can be still executed even if the userKey is empty string. It doesn't happened to scooters that was not reserved yet. The main code goes like this:
func fetchScooters(){
ref?.child("service").child("scooters").observe(.value, with: { (snapshot) in
if snapshot.exists(){
let array:NSArray = snapshot.children.allObjects as NSArray
self.skutery = []
for child in array{
let snap = child as! DataSnapshot
if let dictionary = snap.value as? [String: Any] {
let skuter = ScooterInformation()
skuter.name = dictionary["name"] as? String
skuter.state = dictionary["state"] as? String
skuter.latitude = dictionary["latitude"] as? String
skuter.longitude = dictionary["longitude"] as? String
skuter.battery = dictionary["battery"] as? String
skuter.engine = dictionary["engine"] as? String
skuter.start = dictionary["start"] as? CLong
skuter.userKey = dictionary["userKey"] as? String
self.skutery.append(skuter)
if skuter.userKey == self.userID{
self.hideAllScootersIfUserReserved(scooterInfo: self.skutery)
// THERE IS SOMETHING WRONG....
self.handle = snap.ref.child("feedback").observe(.value, with: { (feedback) in
if let feedback = feedback.value as? Bool{
if feedback && skuter.userKey == self.userID{
print("Feedback received")
self.coundDown.invalidate()
self.timeToConnect = 20
snap.ref.child("feedback").removeValue()
snap.ref.child("check").removeValue()
if self.wantToRunScooter {
self.startScooter()
} else if self.userIsReservedScooter{
self.setStatusAsReserved()
self.userIsReservedScooter = false
}
}
}
})
By hitting the cancel button this is executed:
ref?.child("service").child("scooters").child("\(scooterNumber!)").child("state").setValue("*oF&")
ref?.child("service").child("scooters").child("\(scooterNumber!)").child("userKey").setValue("")
The handle function can be still executed even if the skuter.userKey is not equal to User ID because skuter.userKey should be empty string.
I am struggling with this second day and have no idea what is wrong with this..
I will be very grateful for any help.
Thanks
When the user hits the cancel button, your code only changes the state and the userKey but it does nothing to change the feedback value that is going to come back as true. You need to add something to change the feedback:
ref?.child("service").child("scooters").child("\(scooterNumber!)").child("feedback").setValue(false)
Plus you have:
if feedback && skuter.userKey == self.userID{ .... }
Isnt feedback a Bool and skuter.userKey a String? How can a Bool && String == String ?

Core Data Query, most recent car per year?

In my model I have a Car entity.
Car
year
createDate
name
I want to run a fetch that returns all most recent cars per year where name is not nil (name can be nil).
So, if I have 3 cars with year 2000 and 5 cars with year 2010, I want to get a total of 2 cars out of the fetch request (the most recent for year 2000 and the most recent for year 2010).
I am not sure how to write the proper predicate to achieve this. I looked in the returnsDistinctResults option, but I am not sure that is the right path go go down and it also said that it only works with NSDictionaryResultType which does not work for me.
What would be the proper query/predicate to get this done?
You would be better off simply running over each record, with an algorithm.
Allowing for your Car class, define the following.
struct C {
var year: Int
var created: Date
var name: String?
}
var cars = [C(year: 2009, created: Date(), name: nil), C(year: 2009, created: Date(), name: "Green"), C(year: 2010, created: Date(), name: "Green"), C(year: 2010, created: Date(), name: "Orange"), C(year: 2010, created: Date(), name: "Orange")]
var carsPerYear = [Int: [String: Int]]()
for car in cars {
if let name = car.name {
var info: [String: Int]? = nil
if carsPerYear.keys.contains(car.year) {
info = carsPerYear[car.year]
} else {
info = [String: Int]()
}
if !info!.keys.contains(name) {
info![name] = 0
}
info![name] = info![name]! + 1
carsPerYear[car.year] = info
}
}
for year in carsPerYear.keys {
let info = carsPerYear[year]!
let sorted = info.keys.sorted{ info[$0]! > info[$1]! }
print(year, sorted.first!)
}
Gives output
2009 Green
2010 Orange
Sometimes SQL or CoreData cannot solve the problems easily, it's best to just write sort algorithm.
You can achieve this, if say you're passing an array of years into an algorithm, and expecting a result in the form of a dictionary, with each year you passed in as a key for an object that corresponds to the most recent car of that year.
ie:
let years : [Int] = [2000, 2005]
//The ideal method:
func mostRecentFor<T>(years: [Int]) -> [String:T]
Assuming you only use a small number of search years, and that your database has a small number of cars, you shouldn't have to worry about threading. Otherwise, for this approach you'd have to use concurrency, or a dedicated thread for the fetching to avoid blocking the main thread. For testing purposes you shouldn't need to.
To accomplish this, you would use a method that goes along the following line.
First, a number predicate should be used on the year like other answers have suggested.
For this you would use the date format for NSPredicate:
NSPredicate(format: "date == %#", year)
Your model should, therefore, have the year as a parameter and the actual nsdate as another. You would then use a fecthLimit parameter set to 1, and a sortDescriptor applied to the nsDate key parameter. The combination of the later two will ensure that only the youngest or oldest value is returned for the given year.
func mostRecentFor(years: [Int]) -> [String:Car] {
let result : [String:Car] = [:]
for year in years {
let request: NSFetchRequest<CarModel> = CarModel.fetchRequest()
request.predicate = NSPredicate(format: "date == %# AND name != nil", year)
request.fetchLimit = 1
let NSDateDescriptor: let sectionSortDescriptor = NSSortDescriptor(key: "nsDate", ascending: true)
let descriptors = [NSDateDescriptor]
fetchRequest.sortDescriptors = descriptors
do {
let fetched = try self.managedObjectContext.fetch(request) as
[CarModel]
guard !fetched.isEmpty, fetched.count == 1 else {
print("No Car For year: \(year)")
return
}
result["\(year)"] = new[0].resultingCarStruct //custom parameter here.. see bellow
} catch let err {
print("Error for Year: \(year), \(err.localizedDescription)")
}
}
return result
}
We use ascending set to true here, because we want the first value, the one actually returned due to the fetchLimit value of 1, to be the earliest car of the said year, or the one with the smallest timestamp for it's nsDate key.
This Should give you a simple fetch query for small datastores and testing. Also, creating a method or parameter to interpret CarModel into it's Car struct counterpart could make it simpler to go from CD to your memory objects.
So you'd search for your cars like so:
let years = [1985, 1999, 2005]
let cars = mostRecentFor(years: years)
// cars = ["1985": Car<year: 1985, name: "Chevrolet", nsDate: "April 5th 1985">, "1999" : Car<year: 1999, name: "Toyota Corolla", nsDate: "February 5th 1999">]
// This examples suggests that no cars were found for 2005

retrieving firebase data for iOS app using swift

I'm using firebase to collect data, and i'm trying to retrieve the data in a usable format for an iPhone app, and i can't quite get it out properly. I'm writing the app in Swift.
The data is grouped by a date string then the with a random key and then the data. Eg:
{
"20160304" : {
"-KC-aOwSWpt4dlYmjJE4" : {
"coordinates" : "-37.7811465912404, 145.005993055861",
"event" : "Test event",
"time" : "2016-03-04 07:48:43 +0000"
}, etc...
I'm so far grabbing the data like this:
ref.queryOrderedByKey().observeEventType(.ChildAdded, withBlock: {
snapshot in
//print(snapshot.key) // date
print(snapshot.value)
})
And it returns something like this to the console:
{
"-KD8O0gL7gDGu_hRyFzQ" = {
coordinates = "-37.7540958861003, 145.001224694195";
event = "Test event";
time = "2016-03-18 11:02:32 +0000";
}; etc...
Does anyone know how i can get down to the next level, past the random keys, to the meaningful data? I had trouble before with this for javascript, but it's confusing me using swift.
I'd like to be able to grab the detailed data (bottom level) for a defined date (top level).
Try this code
let jsonLocations = snapshot.valueInExportFormat() as! NSDictionary
let keys = jsonLocations.allKeys
for key in keys {
let json = jsonLocations[key] as! [String: AnyObject]
self.sections.append(Location(JSONObject: json))
}
I usually try to stick to methods of FDatasnapshot as long as possible, which leads to:
ref.queryOrderedByKey().observeEventType(.ChildAdded, withBlock: { snapshot in
for child in snapshot.children {
print(child.key); // -KC-aOwSWpt4dlYmjJE4
print(child.childSnapshotForPath("event").value)
}
});

iOS : Developing for HealthKit, DOB, Height etc coming back as nil

So, I have been tasked with learning HealthKit, seems fairly straight forward. Started building my own app, can get steps etc. However I can't get date of birth, sex, etc. They are always returned as nil
I then downloaded Apple's sample app Fit, again comes back with nothing.
I have authorised both apps and created a medical id in health I am based in the UK? is it a us only thing?
func readProfile() -> ( age:Int?, biologicalsex:HKBiologicalSexObject?, bloodtype:HKBloodTypeObject?)
{
var error:NSError?
var age:Int?
// 1. Request birthday and calculate age
if let birthDay = healthKitStore.dateOfBirthWithError(&error)
{
let today = NSDate()
let calendar = NSCalendar.currentCalendar()
let differenceComponents = NSCalendar.currentCalendar().components(.YearCalendarUnit, fromDate: birthDay, toDate: today, options: NSCalendarOptions(0) )
age = differenceComponents.year
}
if error != nil {
println("Error reading Birthday: \(error)")
}
// 2. Read biological sex
var biologicalSex:HKBiologicalSexObject? = healthKitStore.biologicalSexWithError(&error);
if error != nil {
println("Error reading Biological Sex: \(error)")
}
// 3. Read blood type
var bloodType:HKBloodTypeObject? = healthKitStore.bloodTypeWithError(&error);
if error != nil {
println("Error reading Blood Type: \(error)")
}
// 4. Return the information read in a tuple
return (age, biologicalSex, bloodType)
}
Configuring Medical ID does not populate values for any HealthKit types. Try setting values for each type using the Health Data tab in the Health app.

Resources