I am trying to grab the Heart Rate value from the sensor in real time. The code below activates the workout session (I can see it on the watch), HR sensor lights up, so it is clearly working, but I can't access the value updateHeartRate()
method always returns "No HR detected". Does anyone know how to fix the issue?
let healthStore = HKHealthStore()
var workoutActive = false
var workoutSession : HKWorkoutSession?
let heartRateUnit = HKUnit(fromString: "count/min")
var anchor = HKQueryAnchor(fromValue:
Int(HKAnchoredObjectQueryNoAnchor))
func workoutSession(workoutSession: HKWorkoutSession, didChangeToState toState: HKWorkoutSessionState, fromState: HKWorkoutSessionState, date: NSDate) {
switch toState {
case .Running:
workoutDidStart(date)
case .Ended:
workoutDidEnd(date)
default:
print("Unexpected state \(toState)")
}
}
func workoutSession(workoutSession: HKWorkoutSession, didFailWithError error: NSError) {
// Do nothing for now
NSLog("Workout error: \(error.userInfo)")
}
func workoutDidStart(date : NSDate) {
print("Workout did start")
if let query = createHeartRateStreamingQuery(date) {
print("Using query")
healthStore.executeQuery(query)
} else {
print("cannot start")
}
}
func workoutDidEnd(date : NSDate) {
if let query = createHeartRateStreamingQuery(date) {
healthStore.stopQuery(query)
} else {
}
}
func startBtnTapped() {
if (self.workoutActive) {
//finish the current workout
self.workoutActive = false
print("Finishing Workout")
if let workout = self.workoutSession {
healthStore.endWorkoutSession(workout)
}
} else {
//start a new workout
self.workoutActive = true
startWorkout()
print("Starting Workout")
}
}
func startWorkout() {
self.workoutSession = HKWorkoutSession(activityType: HKWorkoutActivityType.CrossTraining, locationType: HKWorkoutSessionLocationType.Indoor)
self.workoutSession?.delegate = self
healthStore.startWorkoutSession(self.workoutSession!)
}
func createHeartRateStreamingQuery(workoutStartDate: NSDate) -> HKQuery? {
let predicate = HKQuery.predicateForSamplesWithStartDate(workoutStartDate, endDate: nil, options: HKQueryOptions.None)
print("Entered query")
guard let quantityType = HKObjectType.quantityTypeForIdentifier(HKQuantityTypeIdentifierHeartRate) else { return nil }
let heartRateQuery = HKAnchoredObjectQuery(type: quantityType, predicate: nil, anchor: anchor, limit: Int(HKObjectQueryNoLimit)) { (query, sampleObjects, deletedObjects, newAnchor, error) -> Void in
self.updateHeartRate(sampleObjects)
print("Query is configured")
}
heartRateQuery.updateHandler = {(query, samples, deleteObjects, newAnchor, error) -> Void in
self.updateHeartRate(samples)
print("Updating sample")
print(samples)
}
return heartRateQuery
}
func updateHeartRate(samples: [HKSample]?) {
print("Entered updateHR")
guard let heartRateSamples = samples as? [HKQuantitySample] else {
print("No HR detected")
return
}
dispatch_async(dispatch_get_main_queue()) {
print("Enter async")
guard let sample = heartRateSamples.first else{return}
let value = sample.quantity.doubleValueForUnit(self.heartRateUnit)
print(String(UInt16(value)))
// retrieve source from sample
print(sample.sourceRevision.source.name)
}
}
Have you requested authorization to read heart rate samples from HealthKit? If not, your query is most likely receiving an error describing the problem. Try checking for an error in the initial results handler and in the update handler blocks.