I am writing a simple heart rate monitoring application (HKQuantityTypeIdentifierHeartRate) from HealthKit whenever a new health speed value is written to HealthKit.
As seen at WWDC2015 (Session 203), I am using HKAnchoredObjectQuery , which should work to add and remove objects. Whenever I run the application, I call HKQuery for the latest objects and executeQuery , which works fine !!! But I do not have new samples, even if there are samples, but if I bring the application to the background and again to the fore, I get all new heart rates. This is mistake? Or what should I do to control my heart rate without bringing the app to the background?
Here is the code I use (everything is stored in AppDelegate), I call [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; } ] initWithType: quantityType predicate: nil anchor: anchor limit: HKObjectQueryNoLimit resultsHandler: ^ (HKAnchoredObjectQuery * _Nonnull query, NSArray <__ kindof HKSample *> * _Nullable sampleObjects, NSArray <HKDeletedObject *> * _Nullable deletedObjects, HKQueryAnchor -(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; }