Skip to content

Instantly share code, notes, and snippets.

@indisoluble
Last active December 10, 2016 22:21
Show Gist options
  • Save indisoluble/60f564ec96fc958f22801dcaac9bbad1 to your computer and use it in GitHub Desktop.
Save indisoluble/60f564ec96fc958f22801dcaac9bbad1 to your computer and use it in GitHub Desktop.
Simple VC to retrieve all heart rate records in an iPhone and store them in CSV files
/*
Steps:
1. Create a new project using template: 'Single View Application'.
2. Enable HealthKit capabilities for the app.
3. Add these properties to 'Info.plist':
- 'NSHealthShareUsageDescription'
- 'NSHealthUpdateUsageDescription'
4. Copy & paste the content of this file into 'ViewController.swift'.
4. Run the app in your iPhone.
5. Using Xcode, download the container for this app.
6. Open the container. Inside folder 'Documents', there is a bunch of CSV
files with all your heart rate records until the current moment. Each
file is suffixed with the date of the records inside. Each record is a
tuple with the following format:
<Time when the record was saved>,<Heart rate in bpm>
NOTICE: The timezone for all records is GMT.
*/
import HealthKit
import UIKit
class ViewController: UIViewController {
let healthStore = HKHealthStore()
let heartRateType = HKObjectType.quantityType(forIdentifier: .heartRate)!
override func viewDidLoad() {
super.viewDidLoad()
if !HKHealthStore.isHealthDataAvailable() {
print("Health data is NOT available")
return
}
healthStore.requestAuthorization(toShare: nil,
read: [heartRateType],
completion: { [weak self] (success, error) in
guard success else {
print("Request auth. Error:", error!)
return
}
print("Autherization granted")
self?.queryHeartRateSamples()
})
}
func queryHeartRateSamples() {
let predicate = HKQuery.predicateForSamples(withStart: Date(timeIntervalSince1970: 0),
end: Date())
let query = HKSampleQuery(sampleType: heartRateType,
predicate: predicate,
limit: HKObjectQueryNoLimit,
sortDescriptors: nil,
resultsHandler: { [weak self] (_, results, error) in
guard results != nil else {
print("Query. Error:", error!)
return
}
print("Samples retrieved")
self?.processHeartRateSamples(results as! [HKQuantitySample])
})
healthStore.execute(query)
}
func processHeartRateSamples(_ heartRateSamples: [HKQuantitySample]) {
let gmtZone = TimeZone(abbreviation: "GMT")!
var calendar = Calendar(identifier: .gregorian)
calendar.timeZone = gmtZone
let formatter = DateFormatter()
formatter.timeZone = gmtZone
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
var csv: FileHandle?
var csvDate = Date(timeIntervalSince1970: 0)
for sample in heartRateSamples {
let order = calendar.compare(sample.startDate, to: csvDate, toGranularity: .day)
if order != ComparisonResult.orderedSame {
csv?.closeFile()
csvDate = sample.startDate
let csvURL = csvFileURLWithDate(csvDate)
print("Build \(csvURL.lastPathComponent)")
try? "Time,BPM\n".write(to: csvURL, atomically: false, encoding: .utf8)
csv = try? FileHandle(forWritingTo: csvURL)
csv?.seekToEndOfFile()
}
let date = sample.startDate
let heartRate = sample.quantity.doubleValue(for: HKUnit(from: "count/min"))
csv?.write("\(formatter.string(from: date)),\(heartRate)\n".data(using: .utf8)!)
}
csv?.closeFile()
print("Done")
}
func csvFileURLWithDate(_ date: Date) -> URL {
let dirs = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
let docURL = URL(fileURLWithPath: dirs.first!)
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyyMMdd"
let filename = "heartRate-\(dateFormatter.string(from: date)).csv"
return URL(fileURLWithPath: filename, relativeTo: docURL)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment