By Kevin Hou
4 minute read
I was instructed to integrate HealthKit information — specifically pulling steps data — into Breathometer's upcoming app. I'm realitively new to Swift having only started a month ago, so this project was a way for me to get more familiar with the language and IDE. My task was to pull the data from HealhtKit then populate a table within a page of the app. This data could then be used for visualizations, analysis, etc. Here are my main learning goals for this project:
Nested within the authorizeHealthKit function:
1func authorizeHealthKit(completion: ((success:Bool, error:NSError!) -> Void)!) {
2}
3
1let healthKitTypesToRead = NSSet(objects:
2 HKObjectType.characteristicTypeForIdentifier(HKCharacteristicTypeIdentifierDateOfBirth)!, HKObjectType.characteristicTypeForIdentifier(HKCharacteristicTypeIdentifierBiologicalSex)!,
3 HKObjectType.quantityTypeForIdentifier(HKQuantityTypeIdentifierHeight)!,
4 HKObjectType.quantityTypeForIdentifier(HKQuantityTypeIdentifierBodyMass)!
5)
6
1let healthKitTypesToWrite = NSSet(objects:
2 HKObjectType.quantityTypeForIdentifier(HKQuantityTypeIdentifierBodyMass)!
3 )
4
To actually get data from healthkit, create a function within the class. This one, for example, gets your birthdate from health kit:
1func getBirthdateFromHealthKit() -> AnyObject {
2 var birthdate: AnyObject!
3 do {
4 birthdate = try healthKitStore.dateOfBirth()
5 } catch {
6 print("No birthday listed, or permission denied")
7 birthdate = "Not Set"
8 }
9
10 return birthdate
11 }
12
Pulls steps from Healthkit (x number of days) and show it in a table view by creating a new function within the HealthKitManager class.
Returning steps by per day for x number of days:
1func readStepsByDay(sinceDaysAgo: Int, completion: (([HKQuantitySample]!, NSError!) -> Void)!) {
2 let type: HKQuantityType = HKQuantityType.quantityTypeForIdentifier(HKQuantityTypeIdentifierStepCount)!
3 let currentDate = NSDate().dateWithoutTime() // Get current date
4
5 var stepData: [HKQuantitySample] = []
6
7 for daysAgo in 1...sinceDaysAgo {
8 let startDate: NSDate = currentDate.daysAgo(daysAgo) // Set start date
9 let endDate: NSDate = currentDate.daysAgo(daysAgo - 1) // Next day
10 let predicate = HKQuery.predicateForSamplesWithStartDate(startDate, endDate: endDate, options: .None) // Set parameters
11 // Getting all step counts within that day
12 let sampleQuery = HKStatisticsQuery(quantityType: type, quantitySamplePredicate: predicate, options: [.CumulativeSum], completionHandler: { (sampleQuery, result, error ) -> Void in
13
14 if let queryError = error {
15 completion(nil, queryError) // End the master function
16 print("Completion nil")
17 return
18 }
19 if completion != nil {
20 // Create KHQuantitySample for this day
21 let units = HKUnit.countUnit()
22 var quantity: HKQuantity = HKQuantity(unit: units, doubleValue: 0.0)
23 if let value = result?.sumQuantity()?.doubleValueForUnit(HKUnit.countUnit()) {
24 quantity = HKQuantity(unit: units, doubleValue: value)
25 }
26 let currentData = HKQuantitySample(type: HKQuantityType.quantityTypeForIdentifier(HKQuantityTypeIdentifierStepCount)!, quantity: quantity, startDate: startDate, endDate: endDate) // Initiate HKQuantitySample
27 stepData.append(currentData) // Add data to array
28
29 if stepData.count == sinceDaysAgo { // If got all data
30 // If all days are properly fetched -> return [HKQuanitity] sample to master function
31 stepData.sortInPlace({ // Sort by time
32 $0.0.startDate.timeIntervalSinceNow > $0.1.startDate.timeIntervalSinceNow
33 })
34 completion(stepData, nil) // Return error free
35 }
36 }
37 })
38
39 self.healthKitStore.executeQuery(sampleQuery) // Fire the call
40 }
41 }
42
1extension NSDate {
2 func daysAgo(daysAgo: Int) -> NSDate {
3 let result = -24 *60* 60 * Double(daysAgo)
4 return self.dateByAddingTimeInterval(result)
5 }
6
7 func dateWithoutTime() -> NSDate {
8 let dateFormatter = NSDateFormatter()
9 dateFormatter.dateStyle = .MediumStyle // Doesn't include time component
10 let dateToPrint: NSString = dateFormatter.stringFromDate(self) as NSString // Format into medium style string
11 let dateNoTime = dateFormatter.dateFromString(dateToPrint as String) // Get a date from midnight that day
12 return dateNoTime!
13 }
14}
15
1HealthKitManager().readStepsByDay(100, completion: { (mostRecentSteps, error) in
2
3 // Catch error
4 if( error != nil ) {
5 print("Error reading weight from HealthKit Store: \(error.localizedDescription)") // Feedback
6 return // End function
7 }
8
9 for dayCount in mostRecentSteps {
10 print(dayCount.quantity.doubleValueForUnit(HKUnit.countUnit()))
11 }
12 })
13