Reading data from ViewController (NOT apple watch extension)
Swift 5
let health: HKHealthStore = HKHealthStore()
let heartRateUnit:HKUnit = HKUnit(from: "count/min")
let heartRateType:HKQuantityType = HKQuantityType.quantityType(forIdentifier: HKQuantityTypeIdentifier.heartRate)!
var heartRateQuery:HKSampleQuery?
/*Method to get todays heart rate - this only reads data from health kit. */
func getTodaysHeartRates() {
//predicate
let calendar = NSCalendar.current
let now = NSDate()
let components = calendar.dateComponents([.year, .month, .day], from: now as Date)
guard let startDate:NSDate = calendar.date(from: components) as NSDate? else { return }
var dayComponent = DateComponents()
dayComponent.day = 1
let endDate:NSDate? = calendar.date(byAdding: dayComponent, to: startDate as Date) as NSDate?
let predicate = HKQuery.predicateForSamples(withStart: startDate as Date, end: endDate as Date?, options: [])
//descriptor
let sortDescriptors = [
NSSortDescriptor(key: HKSampleSortIdentifierEndDate, ascending: false)
]
heartRateQuery = HKSampleQuery(sampleType: heartRateType, predicate: predicate, limit: 25, sortDescriptors: sortDescriptors, resultsHandler: { (query, results, error) in
guard error == nil else { print("error"); return }
self.printHeartRateInfo(results: results)
}) //eo-query
health.execute(heartRateQuery!)
}//eom
/*used only for testing, prints heart rate info */
private func printHeartRateInfo(results:[HKSample]?)
{
for (_, sample) in results!.enumerated() {
guard let currData:HKQuantitySample = sample as? HKQuantitySample else { return }
print("[\(sample)]")
print("Heart Rate: \(currData.quantity.doubleValue(for: heartRateUnit))")
print("quantityType: \(currData.quantityType)")
print("Start Date: \(currData.startDate)")
print("End Date: \(currData.endDate)")
print("Metadata: \(currData.metadata)")
print("UUID: \(currData.uuid)")
print("Source: \(currData.sourceRevision)")
print("Device: \(currData.device)")
print("---------------------------------\n")
}//eofl
}//eom
Swift 3
let health: HKHealthStore = HKHealthStore()
let heartRateUnit:HKUnit = HKUnit(fromString: "count/min")
let heartRateType:HKQuantityType = HKQuantityType.quantityTypeForIdentifier(HKQuantityTypeIdentifierHeartRate)!
var heartRateQuery:HKSampleQuery?
/*Method to get todays heart rate - this only reads data from health kit. */
func getTodaysHeartRates()
{
//predicate
let calendar = NSCalendar.currentCalendar()
let now = NSDate()
let components = calendar.components([.Year,.Month,.Day], fromDate: now)
guard let startDate:NSDate = calendar.dateFromComponents(components) else { return }
let endDate:NSDate? = calendar.dateByAddingUnit(.Day, value: 1, toDate: startDate, options: [])
let predicate = HKQuery.predicateForSamplesWithStartDate(startDate, endDate: endDate, options: .None)
//descriptor
let sortDescriptors = [
NSSortDescriptor(key: HKSampleSortIdentifierEndDate, ascending: false)
]
heartRateQuery = HKSampleQuery(sampleType: heartRateType,
predicate: predicate,
limit: 25,
sortDescriptors: sortDescriptors)
{ (query:HKSampleQuery, results:[HKSample]?, error:NSError?) -> Void in
guard error == nil else { print("error"); return }
//self.printHeartRateInfo(results)
self.updateHistoryTableViewContent(results)
}//eo-query
health.executeQuery(heartRateQuery!)
}//eom
/*used only for testing, prints heart rate info */
private func printHeartRateInfo(results:[HKSample]?)
{
for(var iter = 0 ; iter < results!.count; iter++)
{
guard let currData:HKQuantitySample = results![iter] as? HKQuantitySample else { return }
print("[\(iter)]")
print("Heart Rate: \(currData.quantity.doubleValueForUnit(heartRateUnit))")
print("quantityType: \(currData.quantityType)")
print("Start Date: \(currData.startDate)")
print("End Date: \(currData.endDate)")
print("Metadata: \(currData.metadata)")
print("UUID: \(currData.UUID)")
print("Source: \(currData.sourceRevision)")
print("Device: \(currData.device)")
print("---------------------------------\n")
}//eofl
}//eom
Reading data with apple watch extension:
to execute query in apple watch, do the following:
heartRateQuery = self.createStreamingQuery()
health.executeQuery(heartRateQuery!)
don't forget the properties:
let health: HKHealthStore = HKHealthStore()
let heartRateUnit:HKUnit = HKUnit(fromString: "count/min")
let heartRateType:HKQuantityType = HKQuantityType.quantityTypeForIdentifier(HKQuantityTypeIdentifierHeartRate)!
var heartRateQuery:HKQuery?
/*The below methods has no Limit, query for heart infinitely once its the query its executed */
private func createStreamingQuery() -> HKQuery
{
let queryPredicate = HKQuery.predicateForSamplesWithStartDate(NSDate(), endDate: nil, options: .None)
let query:HKAnchoredObjectQuery = HKAnchoredObjectQuery(type: self.heartRateType, predicate: queryPredicate, anchor: nil, limit: Int(HKObjectQueryNoLimit))
{ (query:HKAnchoredObjectQuery, samples:[HKSample]?, deletedObjects:[HKDeletedObject]?, anchor:HKQueryAnchor?, error:NSError?) -> Void in
if let errorFound:NSError = error
{
print("query error: \(errorFound.localizedDescription)")
}
else
{
//printing heart rate
if let samples = samples as? [HKQuantitySample]
{
if let quantity = samples.last?.quantity
{
print("\(quantity.doubleValueForUnit(heartRateUnit))")
}
}
}
}//eo-query
query.updateHandler =
{ (query:HKAnchoredObjectQuery, samples:[HKSample]?, deletedObjects:[HKDeletedObject]?, anchor:HKQueryAnchor?, error:NSError?) -> Void in
if let errorFound:NSError = error
{
print("query-handler error : \(errorFound.localizedDescription)")
}
else
{
//printing heart rate
if let samples = samples as? [HKQuantitySample]
{
if let quantity = samples.last?.quantity
{
print("\(quantity.doubleValueForUnit(heartRateUnit))")
}
}
}//eo-non_error
}//eo-query-handler
return query
}//eom
How to request authorization?
func requestAuthorization()
{
//reading
let readingTypes:Set = Set( [heartRateType] )
//writing
let writingTypes:Set = Set( [heartRateType] )
//auth request
health.requestAuthorizationToShareTypes(writingTypes, readTypes: readingTypes) { (success, error) -> Void in
if error != nil
{
print("error \(error?.localizedDescription)")
}
else if success
{
}
}//eo-request
}//eom