Heart Rate With Apple's Healthkit

依然范特西╮ 提交于 2019-12-02 02:46:46

问题


I'm currently using Healthkit in an app and have no problems getting info for most types, but am having trouble with the Heart Rate. Every time I try to read a sample, I get "0" as a result. I have an Apple Watch, and my Heart Rate gets fed into the Apple Health app, and can visually see it there, so it's not a hardware issue. I only need to display it, no need to write the data back. It asks my permission on first run to allow access to the heart rate, so shouldn't be any issues with that code, but I'll post it anyways.

Most examples that I can find with heart rate detection are either in Swift, which I prefer to stay away from, or outdates bluetooth/camera methods.

Here is what I'm using, which is mostly copy and pasted from the code that retrieves steps, walking distance, etc elsewhere in my code... so I've probably got something in this block thats not compatible with the heart rate data type, but I can't find it. Right now it looks like it will be getting the average heart rate for the day, and not the latest sample, which is fine for now, as long as I can see SOME type of data being fed to the app. I couldn't find a way to poll the latest sample of the heart rate, which leads me to believe I'm using the wrong method entirely, but can't find any other info or samples that work. I've tried about 8 different online sample code/projects, none of which I can get to produce anything other than "0" as a result (so please no links to example code... I've tried all the ones available already... google, github, etc, etc, so any links will probably get an "I've already tested that one and same error" response, lol). Here's what I'm using right now:

The block that I'm 99.9% sure is giving me the issues:

    - (void)queryHealthDataHeart{
    HKQuantityType *typeHeart =[HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierHeartRate];
    NSDate *now = [NSDate date];
    NSCalendar *calendar = [NSCalendar autoupdatingCurrentCalendar];
    NSDateComponents *components = [calendar components:NSCalendarUnitYear| NSCalendarUnitMonth | NSCalendarUnitDay
                                               fromDate:now];
    NSDate *beginOfDay = [calendar dateFromComponents:components];
    NSPredicate *predicate = [HKQuery predicateForSamplesWithStartDate:beginOfDay endDate:now options:HKQueryOptionStrictStartDate];

    HKStatisticsQuery *squery = [[HKStatisticsQuery alloc] initWithQuantityType:typeHeart quantitySamplePredicate:predicate options:HKStatisticsOptionNone completionHandler:^(HKStatisticsQuery *query, HKStatistics *result, NSError *error) {
        dispatch_async(dispatch_get_main_queue(), ^{
            HKQuantity *quantity = result.averageQuantity;
            double beats = [quantity doubleValueForUnit:[HKUnit heartBeatsPerMinuteUnit]];
            _lblHeart.text = [NSString stringWithFormat:@"%.f",beats];
        }
        );
    }];
    [self.healthStore executeQuery:squery];
}

Code to check permissions:

- (void)readHealthKitData{
HKHealthStore *healthStore = [[HKHealthStore alloc] init];
NSSet *shareObjectTypes = [NSSet setWithObjects:
                           nil];
NSSet *readObjectTypes  = [NSSet setWithObjects:
                           [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierDistanceWalkingRunning],
                           [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierHeartRate],
                           [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierFlightsClimbed],
                           [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount],
                           nil];
// Request access
[healthStore requestAuthorizationToShareTypes:shareObjectTypes
                                    readTypes:readObjectTypes
                                   completion:^(BOOL success, NSError *error) {
                                       if(success == YES)
                                       {
                                           [self queryHealthData];
                                           [self queryHealthDataDistance];
                                           [self queryHealthDataFlights];
                                           [self queryHealthDataHeart];
                                       }
                                       else
                                       {
                                           // Determine if it was an error or if the
                                           // user just canceld the authorization request
                                       }

                                   }];}

And above my - (void)queryHealthDataHeart, I have the proper references, as seen here:

#import "AN_Pedometer.h"
#import <HealthKit/HealthKit.h>

@interface AN_Pedometer (){
UILabel *lbCMData;
NSDateFormatter *formatter;}
@property (nonatomic, strong) CMPedometer *pedometer;
@property (nonatomic, strong) HKHealthStore *healthStore;
@end
@interface HKUnit (HKManager)
+ (HKUnit *)heartBeatsPerMinuteUnit;
@end

@implementation HKUnit (HKManager)

+ (HKUnit *)heartBeatsPerMinuteUnit {
return [[HKUnit countUnit] unitDividedByUnit:[HKUnit minuteUnit]];
}

@end

回答1:


From what I read and if I'm correct, you are trying to read the heart rate from the beginning of the day up till now.

Check your start date and end date by logging them out after using a date formatter. Could be possible that the start time and the end time are the same, that is why you get 0 as the result.

NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ssZZZ"];
NSString *dateString = [dateFormatter stringFromDate:beginOfDay];
NSLog(@"%@", dateString);

You should also set the hour minute and second to zero to ensure that you are getting a time of the start of the day.

NSDateComponents *components = [calendar components:NSCalendarUnitYear| NSCalendarUnitMonth | NSCalendarUnitDay
                                           fromDate:now];
components.hour = 0;
components.minute = 0;
components.second = 0;

Hope this helps.




回答2:


if you want to get averageQuantity ask for it in your HKStatisticsQuery options. otherwise it will always be nil (ie. not calculated): options parameter should be set to HKStatisticsOptionDiscreteAverage, NOT HKStatisticsOptionNone



来源:https://stackoverflow.com/questions/31440205/heart-rate-with-apples-healthkit

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!