Reputation: 59
I have had a look around the internet and also had a read of what seems relevant in the documentation at developer.apple.com. there are a few tutorials around dealing with how to set up queries but i have not found any easy way to extract the data values from HKSamples returned by any query. Im sure there must be something more elegant and versatile than string processing in this case.
heres the code i have which works well for me:
var anchor : HKQueryAnchor? = nil
func newStreamingQuery(withIdentifier: HKQuantityTypeIdentifier) {
let hkqType = HKQuantityType.quantityType(forIdentifier: withIdentifier)!
let observer = HKObserverQuery(sampleType: hkqType, predicate: nil, updateHandler:
{(queryResult, completionHandler, error) in
if (error != nil) { print( error!.localizedDescription) ; return}
// We recreate the query every time becuase it can only be used once.
let query = HKAnchoredObjectQuery(type: hkqType, predicate: nil, anchor: self.anchor, limit: HKObjectQueryNoLimit, resultsHandler: { (query, samples, deleted, newAnchor, error) in
if error != nil {print(error!) ; return}
self.anchor = newAnchor
print ("\(samples!.count)\n")
for i in ( 0..<samples!.count)
{ // What do i do to access the data in s sensible fassion.
let hktype = samples![i]
let value = hktype// do something with hktype to get the value out
let time = hktype// do something with hktype to get the time out
print("\(value)\n")}
completionHandler()
})
WatchHelthKitHelper.healthStore.execute(query)
})
WatchHelthKitHelper.healthStore.execute(observer)
}
If I call it like this:
func startStreamingQuery(){
newStreamingQuery(withIdentifier: HKQuantityTypeIdentifier.heartRate)
}
I get nice output like this:
1
1.56667 count/s 723404AC-C90C-4374-B75A-AAE7CD166115 "Jason’s Apple Watch" (3.1) "Apple Watch" (2017-01-02 15:59:42 +0800 - 2017-01-02 15:59:42 +0800)
1
1.63333 count/s 148B311D-57EE-4D65-B560-765E7E8319C6 "Jason’s Apple Watch" (3.1) "Apple Watch" (2017-01-02 15:59:46 +0800 - 2017-01-02 15:59:46 +0800)
1
1.65 count/s F92DD3AE-0527-48D1-B75B-3F04D6C0ABCF "Jason’s Apple Watch" (3.1) "Apple Watch" (2017-01-02 15:59:49 +0800 - 2017-01-02 15:59:49 +0800)
1
1.63333 count/s 0CF55099-6D51-408D-B322-00A8F469AF54 "Jason’s Apple Watch" (3.1) "Apple Watch" (2017-01-02 15:59:53 +0800 - 2017-01-02 15:59:53 +0800)
1
1.48333 count/s 1FCD3472-081F-4479-80F2-543A45CCA221 "Jason’s Apple Watch" (3.1) "Apple Watch" (2017-01-02 16:00:00 +0800 - 2017-01-02 16:00:00 +0800)
Im sure it is easy to do this but i feel it must be hidden under a concept i do not understand at the moment.
Much gratitude for your answers.
Also if anyone knows how to get more detailed heart wave/pulse data id love to hear about it.
Upvotes: 3
Views: 2881
Reputation: 4174
This might work for you.
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
Upvotes: 5