xcode Apple Watch 上的心率数据

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/28858667/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 06:45:55  来源:igfitidea点击:

Heart Rate data on apple Watch

objective-cxcodewatchkit

提问by Andrew Garcia

Can we access the heart rate directly from the apple watch? I know this is a duplicate question, but no one has asked this in like 5 months. I know you can access it from the Health App but I'm not sure how "real-time" that will be.

我们可以直接从 Apple Watch 访问心率吗?我知道这是一个重复的问题,但在 5 个月内没有人问过这个问题。我知道您可以从 Health App 访问它,但我不确定它的“实时性”如何。

采纳答案by Stephen Johnson

There is no direct way to access any sensors on the Apple Watch. You will have to rely on access from HealthKit.

无法直接访问 Apple Watch 上的任何传感器。您将不得不依赖 HealthKit 的访问权限。

An Apple evangelist said this

一位苹果布道者这样说

It is not possible to create a heart monitor app at this time. The data isn't guaranteed to be sent to iPhone in real-time, so you won't be able to determine what's going on in any timely fashion.

目前无法创建心脏监测器应用程序。无法保证数据会实时发送到 iPhone,因此您将无法及时确定发生了什么。

See https://devforums.apple.com/message/1098855#1098855

https://devforums.apple.com/message/1098855#1098855

回答by casillas

Heart Rate Raw Data information is now availablein Watchkit for watchOS 2.0.

心率原始数据信息现在可以Watchkit for watchOS 2.0.

WatchOS 2includes many enhancements to other existing frameworks such as HealthKit, enabling access to the health sensors that access heart rate and health information in real-time.

WatchOS 2包括对其他现有框架的许多增强功能,例如HealthKit,允许访问实时访问心率和健康信息的健康传感器。

You could check this information in the following session which is total 30 minutes presentation.If you do not want to watch entire session, then you directly jump to Healthkit APIfeatures which is in between 25-28 min:

您可以在以下总时长 30 分钟的演示中查看此信息。如果您不想观看整个会话,那么您可以直接跳转到Healthkit API25-28 分钟之间的功能:

WatchKit for watchOS 2.0 Session in WWDC 2015

WWDC 2015 中 watchOS 2.0 Session 的 WatchKit

Here is the source code implementation link

这是源代码实现链接

As stated in the HKWorkout Class Reference:

HKWorkout Class Reference 所述

The HKWorkoutclass is a concrete subclass of the HKSampleclass. HealthKituses workouts to track a wide range of activities. The workout object not only stores summary information about the activity (for example, duration, total distance, and total energy burned), it also acts as a container for other samples. You can associate any number of samples with a workout. In this way, you can add detailed information relevant to the workout.

HKWorkout班是一个具体子HKSample类。 HealthKit使用锻炼来跟踪各种活动。锻炼对象不仅存储有关活动的摘要信息(例如,持续时间、总距离和消耗的总能量),还充当其他样本的容器。您可以将任意数量的样本与锻炼相关联。通过这种方式,您可以添加与锻炼相关的详细信息。

In that given link, the following part of the code defines sample rate of heartRate

在该给定链接中,代码的以下部分定义了 heartRate 的采样率

NSMutableArray *samples = [NSMutableArray array];

HKQuantity *heartRateForInterval =
[HKQuantity quantityWithUnit:[HKUnit unitFromString:@"count/min"]
                 doubleValue:95.0];

HKQuantitySample *heartRateForIntervalSample =
[HKQuantitySample quantitySampleWithType:heartRateType
                                quantity:heartRateForInterval
                               startDate:intervals[0]
                                 endDate:intervals[1]];

[samples addObject:heartRateForIntervalSample];

As they state there:

正如他们所说:

You need to fine tune the exact length of your associated samples based on the type of workout and the needs of your app. Using 5 minute intervals minimizes the amount of memory needed to store the workout , while still providing a general sense of the change in intensity over the course of a long workout. Using 5 second intervals provides a much-more detailed view of the workout, but requires considerably more memory and processing.

您需要根据锻炼类型和应用程序的需求微调相关样本的确切长度。使用 5 分钟的间隔可以最大限度地减少存储锻炼所需的内存量,同时仍然提供长时间锻炼过程中强度变化的总体感觉。使用 5 秒间隔可提供更详细的锻炼视图,但需要更多的内存和处理。

回答by shoan

After exploring HealthKit and WatchKit Extension, My findings are as follows:

在探索 HealthKit 和 WatchKit Extension 之后,我的发现如下:

  1. We do not need the WatchKit Extension to get the Heart Rate Data.
  2. You just need to have an iPhone with paired Apple watch (which is obvious)
  3. The Default Apple Watch Heart Rate monitor app updates the HealthKit data immediately only when it is in the foreground.
  4. When the Default Apple Watch Heart Rate monitor app is in the Background, it updates the HealthKit data at the interval of 9-10 mins.
  5. To get the Heart rate data from the HealthKit following query needs to be fired periodically.

    func getSamples()
    {
        let heartrate =HKQuantityType.quantityTypeForIdentifier(HKQuantityTypeIdentifierHeartRate)
        let sort = [
           NSSortDescriptor(key: HKSampleSortIdentifierStartDate, ascending: false)
    ]
    let heartRateUnit = HKUnit(fromString: "count/min")
    let sampleQuery = HKSampleQuery(sampleType: heartrate!, predicate: nil, limit: 1, sortDescriptors: sort, resultsHandler: { [unowned self] (query, results, error) in
        if let results = results as? [HKQuantitySample]
        {
             let sample = results[0] as HKQuantitySample
    
            let value = sample.quantity.doubleValueForUnit(self.heartRateUnit)
            print (value)
            let rate = results[0]
            print(results[0])
            print(query)
            self.updateHeartRate(results)
        }
      })
        healthStore?.executeQuery(sampleQuery)
    
    }
    
    func updateHeartRate(samples: [HKSample]?)
    {
        guard let heartRateSamples = samples as? [HKQuantitySample] else {return}
        dispatch_async(dispatch_get_main_queue()) {
            guard let sample = heartRateSamples.first else{return}
            let value = sample.quantity.doubleValueForUnit(self.heartRateUnit)
            self.heartRateLabel.text = String(UInt16(value))
            let date = sample.startDate
            let dateFormatter = NSDateFormatter()
            dateFormatter.dateFormat = "yyyy-MM-dd hh:mm:ss"
            self.timeStampLabel.text = dateFormatter.stringFromDate(date)
        }
    }
    
  1. 我们不需要 WatchKit 扩展来获取心率数据。
  2. 你只需要一部 iPhone 和配对的 Apple Watch(这很明显)
  3. 默认的 Apple Watch 心率监测器应用程序仅在其处于前台时立即更新 HealthKit 数据。
  4. 当默认 Apple Watch 心率监测器应用程序在后台时,它会以 9-10 分钟的间隔更新 HealthKit 数据。
  5. 要从 HealthKit 获取心率数据,需要定期触发以下查询。

    func getSamples()
    {
        let heartrate =HKQuantityType.quantityTypeForIdentifier(HKQuantityTypeIdentifierHeartRate)
        let sort = [
           NSSortDescriptor(key: HKSampleSortIdentifierStartDate, ascending: false)
    ]
    let heartRateUnit = HKUnit(fromString: "count/min")
    let sampleQuery = HKSampleQuery(sampleType: heartrate!, predicate: nil, limit: 1, sortDescriptors: sort, resultsHandler: { [unowned self] (query, results, error) in
        if let results = results as? [HKQuantitySample]
        {
             let sample = results[0] as HKQuantitySample
    
            let value = sample.quantity.doubleValueForUnit(self.heartRateUnit)
            print (value)
            let rate = results[0]
            print(results[0])
            print(query)
            self.updateHeartRate(results)
        }
      })
        healthStore?.executeQuery(sampleQuery)
    
    }
    
    func updateHeartRate(samples: [HKSample]?)
    {
        guard let heartRateSamples = samples as? [HKQuantitySample] else {return}
        dispatch_async(dispatch_get_main_queue()) {
            guard let sample = heartRateSamples.first else{return}
            let value = sample.quantity.doubleValueForUnit(self.heartRateUnit)
            self.heartRateLabel.text = String(UInt16(value))
            let date = sample.startDate
            let dateFormatter = NSDateFormatter()
            dateFormatter.dateFormat = "yyyy-MM-dd hh:mm:ss"
            self.timeStampLabel.text = dateFormatter.stringFromDate(date)
        }
    }
    

Please update me if anyone gets more information.
Happy Coding.

如果有人获得更多信息,请更新我。
快乐编码。

回答by NeilNie

You can get heart rate data by starting a workout and query heart rate data from healthkit.

您可以通过开始锻炼获取心率数据,并从 healthkit 查询心率数据。

  1. Ask for premission for reading workout data.

    HKHealthStore *healthStore = [[HKHealthStore alloc] init];
    HKQuantityType *type = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierHeartRate];
    HKQuantityType *type2 = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierDistanceWalkingRunning];
    HKQuantityType *type3 = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierActiveEnergyBurned];
    
    [healthStore requestAuthorizationToShareTypes:nil readTypes:[NSSet setWithObjects:type, type2, type3, nil] completion:^(BOOL success, NSError * _Nullable error) {
    
    if (success) {
        NSLog(@"health data request success");
    
    }else{
        NSLog(@"error %@", error);
    }
    }];
    
  2. In AppDelegate on iPhone, respond this this request

    -(void)applicationShouldRequestHealthAuthorization:(UIApplication *)application{
    
    [healthStore handleAuthorizationForExtensionWithCompletion:^(BOOL success, NSError * _Nullable error) {
            if (success) {
                NSLog(@"phone recieved health kit request");
            }
        }];
    }
    
  3. Then implement Healthkit Delegate:

    -(void)workoutSession:(HKWorkoutSession *)workoutSession didFailWithError:(NSError *)error{
    
    NSLog(@"session error %@", error);
    }
    
    -(void)workoutSession:(HKWorkoutSession *)workoutSession didChangeToState:(HKWorkoutSessionState)toState fromState:(HKWorkoutSessionState)fromState date:(NSDate *)date{
    
    dispatch_async(dispatch_get_main_queue(), ^{
        switch (toState) {
            case HKWorkoutSessionStateRunning:
    
                //When workout state is running, we will excute updateHeartbeat
                [self updateHeartbeat:date];
                NSLog(@"started workout");
            break;
    
            default:
            break;
        }
        });
    }
    
  4. Now it's time to write **[self updateHeartbeat:date]**

    -(void)updateHeartbeat:(NSDate *)startDate{
    
        //first, create a predicate and set the endDate and option to nil/none 
        NSPredicate *Predicate = [HKQuery predicateForSamplesWithStartDate:startDate endDate:nil options:HKQueryOptionNone];
    
        //Then we create a sample type which is HKQuantityTypeIdentifierHeartRate
        HKSampleType *object = [HKSampleType quantityTypeForIdentifier:HKQuantityTypeIdentifierHeartRate];
    
        //ok, now, create a HKAnchoredObjectQuery with all the mess that we just created.
        heartQuery = [[HKAnchoredObjectQuery alloc] initWithType:object predicate:Predicate anchor:0 limit:0 resultsHandler:^(HKAnchoredObjectQuery *query, NSArray<HKSample *> *sampleObjects, NSArray<HKDeletedObject *> *deletedObjects, HKQueryAnchor *newAnchor, NSError *error) {
    
        if (!error && sampleObjects.count > 0) {
            HKQuantitySample *sample = (HKQuantitySample *)[sampleObjects objectAtIndex:0];
            HKQuantity *quantity = sample.quantity;
            NSLog(@"%f", [quantity doubleValueForUnit:[HKUnit unitFromString:@"count/min"]]);
        }else{
            NSLog(@"query %@", error);
        }
    
        }];
    
        //wait, it's not over yet, this is the update handler
        [heartQuery setUpdateHandler:^(HKAnchoredObjectQuery *query, NSArray<HKSample *> *SampleArray, NSArray<HKDeletedObject *> *deletedObjects, HKQueryAnchor *Anchor, NSError *error) {
    
         if (!error && SampleArray.count > 0) {
            HKQuantitySample *sample = (HKQuantitySample *)[SampleArray objectAtIndex:0];
            HKQuantity *quantity = sample.quantity;
            NSLog(@"%f", [quantity doubleValueForUnit:[HKUnit unitFromString:@"count/min"]]);
         }else{
            NSLog(@"query %@", error);
         }
    }];
    
        //now excute query and wait for the result showing up in the log. Yeah!
        [healthStore executeQuery:heartQuery];
    }
    
  1. 要求获得阅读锻炼数据的权限

    HKHealthStore *healthStore = [[HKHealthStore alloc] init];
    HKQuantityType *type = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierHeartRate];
    HKQuantityType *type2 = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierDistanceWalkingRunning];
    HKQuantityType *type3 = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierActiveEnergyBurned];
    
    [healthStore requestAuthorizationToShareTypes:nil readTypes:[NSSet setWithObjects:type, type2, type3, nil] completion:^(BOOL success, NSError * _Nullable error) {
    
    if (success) {
        NSLog(@"health data request success");
    
    }else{
        NSLog(@"error %@", error);
    }
    }];
    
  2. iPhone 上的 AppDelegate 中,响应此请求

    -(void)applicationShouldRequestHealthAuthorization:(UIApplication *)application{
    
    [healthStore handleAuthorizationForExtensionWithCompletion:^(BOOL success, NSError * _Nullable error) {
            if (success) {
                NSLog(@"phone recieved health kit request");
            }
        }];
    }
    
  3. 然后执行Healthkit Delegate

    -(void)workoutSession:(HKWorkoutSession *)workoutSession didFailWithError:(NSError *)error{
    
    NSLog(@"session error %@", error);
    }
    
    -(void)workoutSession:(HKWorkoutSession *)workoutSession didChangeToState:(HKWorkoutSessionState)toState fromState:(HKWorkoutSessionState)fromState date:(NSDate *)date{
    
    dispatch_async(dispatch_get_main_queue(), ^{
        switch (toState) {
            case HKWorkoutSessionStateRunning:
    
                //When workout state is running, we will excute updateHeartbeat
                [self updateHeartbeat:date];
                NSLog(@"started workout");
            break;
    
            default:
            break;
        }
        });
    }
    
  4. 现在是时候写了 **[self updateHeartbeat:date]**

    -(void)updateHeartbeat:(NSDate *)startDate{
    
        //first, create a predicate and set the endDate and option to nil/none 
        NSPredicate *Predicate = [HKQuery predicateForSamplesWithStartDate:startDate endDate:nil options:HKQueryOptionNone];
    
        //Then we create a sample type which is HKQuantityTypeIdentifierHeartRate
        HKSampleType *object = [HKSampleType quantityTypeForIdentifier:HKQuantityTypeIdentifierHeartRate];
    
        //ok, now, create a HKAnchoredObjectQuery with all the mess that we just created.
        heartQuery = [[HKAnchoredObjectQuery alloc] initWithType:object predicate:Predicate anchor:0 limit:0 resultsHandler:^(HKAnchoredObjectQuery *query, NSArray<HKSample *> *sampleObjects, NSArray<HKDeletedObject *> *deletedObjects, HKQueryAnchor *newAnchor, NSError *error) {
    
        if (!error && sampleObjects.count > 0) {
            HKQuantitySample *sample = (HKQuantitySample *)[sampleObjects objectAtIndex:0];
            HKQuantity *quantity = sample.quantity;
            NSLog(@"%f", [quantity doubleValueForUnit:[HKUnit unitFromString:@"count/min"]]);
        }else{
            NSLog(@"query %@", error);
        }
    
        }];
    
        //wait, it's not over yet, this is the update handler
        [heartQuery setUpdateHandler:^(HKAnchoredObjectQuery *query, NSArray<HKSample *> *SampleArray, NSArray<HKDeletedObject *> *deletedObjects, HKQueryAnchor *Anchor, NSError *error) {
    
         if (!error && SampleArray.count > 0) {
            HKQuantitySample *sample = (HKQuantitySample *)[SampleArray objectAtIndex:0];
            HKQuantity *quantity = sample.quantity;
            NSLog(@"%f", [quantity doubleValueForUnit:[HKUnit unitFromString:@"count/min"]]);
         }else{
            NSLog(@"query %@", error);
         }
    }];
    
        //now excute query and wait for the result showing up in the log. Yeah!
        [healthStore executeQuery:heartQuery];
    }
    

You also have a turn on Healthkit in capbilities. Leave a comment below if you have any questions.

您还可以打开 Healthkit 的功能。如果您有任何问题,请在下方发表评论。