I am writing a simple app to monitor the heart rate (HKQuantityTypeIdentifierHeartRate) from HealthKit whenever a new health rate value is written to HealthKit.
As seen at WWDC2015 (session 203) I am using a HKAnchoredObjectQuery which should work for adding and deleting objects. Whenever I start the app I am calling the HKQuery for the newest objects and executingQuery which works fine!!! But I am getting no new samples even if the samples are there, but if I bring the app to the background and again to the foreground I am getting all the new heart rates. IS IT A BUG? Or what shall I do to monitor the heart rate without bringing the app to the back- and foreground?
Here is the code I am using (everything is stored in the AppDelegate), I am calling [self requestAccessDataTypes];
from didFinishLaunchingWithOptions:
[healthStore enableBackgroundDeliveryForType:sampleType frequency:HKUpdateFrequencyImmediate withCompletion:^(BOOL success, NSError *error) {}];
HKQuery *query = [self createHeartRateStreamingQuery:datum];
if (query) {
[healthStore executeQuery:query];
}
else
{
NSLog(@"workout can not start");
}
-(HKQuery*)createHeartRateStreamingQuery:(NSDate*)workoutStartDate
{
NSLog(@"%@ - createHeartRateStreamingQuery", [self class]);
if ([HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierHeartRate]) {
HKQuantityType *quantityType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierHeartRate];
HKAnchoredObjectQuery * heartRateQuery = [[HKAnchoredObjectQuery alloc] initWithType:quantityType predicate:nil anchor:anchor limit:HKObjectQueryNoLimit resultsHandler:^(HKAnchoredObjectQuery * _Nonnull query, NSArray<__kindof HKSample *> * _Nullable sampleObjects, NSArray<HKDeletedObject *> * _Nullable deletedObjects, HKQueryAnchor * _Nullable newAnchor, NSError * _Nullable error) {
if (!error) {
anchor = newAnchor;
[self updateHeartRate:sampleObjects];
}
}];
heartRateQuery.updateHandler = ^void(HKAnchoredObjectQuery *query, NSArray<__kindof HKSample *> * __nullable addedObjects, NSArray<HKDeletedObject *> * __nullable deletedObjects, HKQueryAnchor * __nullable newAnchor, NSError * __nullable error)
{
if (!error) {
anchor = newAnchor;
[self updateHeartRate:addedObjects];
}
};
return heartRateQuery;
}
return nil;
}
You are missing a crucial piece for observing changes in HealthKit. It's called HKObserverQuery
.
Docs
Observer queries set up a long-running task on a background queue. This task watches the HealthKit store, and alerts you whenever matching data is saved to or removed from the store. Observer queries let your app respond to changes made by other apps and devices.
Recap:
You have to wrap your HKAnchoredObjectQuery
in HKObserverQuery
with background delivery enabled in order to get notified about updates. You can then execute your query whenever that happens.
Note 1: HKObserverQuery
's update handler will NOT give you any Apple Health data samples. You still have to execute your HKAnchoredObjectQuery
with a proper anchor to get the samples.
Note 2: You have to set up HKObserverQuery
every time your app launches.
For further info, look at my answer here.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With