Objective c 苹果手表上的心率数据

Objective c 苹果手表上的心率数据,objective-c,xcode,watchkit,Objective C,Xcode,Watchkit,我们可以直接从苹果手表上获取心率吗?我知道这是一个重复的问题,但5个月以来没有人问过这个问题。我知道你可以通过健康应用程序访问它,但我不确定它的“实时性”如何。无法直接访问Apple Watch上的任何传感器。您必须依赖HealthKit的访问权限 一位苹果传道者这样说 此时无法创建心脏监护仪应用程序。这个 数据不能保证实时发送到iPhone,所以你不会 能够及时确定发生了什么 请参见心率原始数据信息现已在Watchkit for watchOS 2.0中提供 WatchOS 2包括对其他现有框

我们可以直接从苹果手表上获取心率吗?我知道这是一个重复的问题,但5个月以来没有人问过这个问题。我知道你可以通过健康应用程序访问它,但我不确定它的“实时性”如何。

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

一位苹果传道者这样说

此时无法创建心脏监护仪应用程序。这个 数据不能保证实时发送到iPhone,所以你不会 能够及时确定发生了什么


请参见心率原始数据信息现已在
Watchkit for watchOS 2.0
中提供

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

您可以在以下总共30分钟的课程中查看此信息。如果您不想观看整个课程,请直接跳到25-28分钟之间的
Healthkit API
功能:

下面是源代码实现

如合同所述:

HKWorkout
类是
HKSample
类的一个具体子类。
HealthKit
使用训练来跟踪各种活动。这个 训练对象不仅存储有关活动的摘要信息 (例如,持续时间、总距离和燃烧的总能量),它 也可作为其他样品的容器。你可以联系任何人 训练的样本数。通过这种方式,您可以添加详细信息 与训练相关的信息

在给定的链接中,下面的代码部分定义了心率的采样率

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];
正如他们所说:

您需要微调关联样本的确切长度 基于训练类型和应用程序的需求。使用5分钟 间隔时间将存储训练所需的内存量降至最低, 同时还提供了一个整体的感觉,随着时间的推移强度的变化 长期锻炼的过程。使用5秒的间隔可以提供 更详细的训练视图,但需要更多 内存和处理


在探索HealthKit和WatchKit扩展后,我的发现如下:

  • 我们不需要WatchKit扩展来获取心率数据

  • 你只需要有一台iPhone和一对苹果手表(很明显)

  • 默认的Apple Watch心率监视器应用程序只有在前台才会立即更新HealthKit数据

  • 默认的Apple Watch心率监视器应用程序在后台时,每隔9-10分钟更新HealthKit数据

  • 要从HealthKit获取心率数据,需要定期触发以下查询

    func getSamples(){
    让heathStore=HKHealthStore()
    让心率=HKQuantityType.quantityType(用于标识符:。心率)
    let sort:[NSSortDescriptor]=[
    .init(键:HKSampleSortIdentifierStartDate,升序:false)
    ]
    让sampleQuery=HKSampleQuery(sampleType:heartrate!,谓词:nil,限制:1,sortDescriptors:sort,resultsHandler:resultsHandler)
    heathStore.execute(sampleQuery)
    }
    func resultsHandler(查询:HKSampleQuery,结果:[HKSample]?,错误:error?){
    保护错误==nil else{
    打印(“无法读取心率数据”,错误!)
    返回
    }
    guard let sample=results?.first as?HKQuantitySample else{return}
    //let heartRateUnit:HKUnit=.init(从“计数/分钟”)
    //设doubleValue=sample.quantity.doubleValue(for:heartRateUnit)
    打印(“心率为”,样本)
    }
    
  • 如果有人获得更多信息,请更新我。
    快乐编码

    更新


    我已将您的代码更新为清晰和通用,并注意您需要获得授权才能读取HeathKit数据并添加
    info.plist
    key
    Privacy-健康记录使用说明

    您可以通过开始训练获取心率数据并从healthkit查询心率数据

  • 要求获得阅读训练数据的事先许可

    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);
    }
    }];
    
  • 在iPhone上的AppDelegate中,响应此请求

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

    -(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;
        }
        });
    }
    
  • 现在是编写
    **[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];
    }
    
    -(void)updateHeartbeat:(NSDate*)startDate{
    //首先,创建一个谓词并将endDate和选项设置为nil/none
    NSPredicate*谓词=[HKQuery PREDICTEFORSAMPLESWITHSTARTDATE:startDate endDate:nil options:HKQUERYOPTIONONNE];
    //然后我们创建一个样本类型,即HKQuantityTypeIdentifierHeartate
    HKSampleType*对象=[HKSampleType quantityTypeForIdentifier:HKQuantityTypeIdentifierHeartate];
    //好,现在,用我们刚才创建的所有混乱创建一个HKAnchoredObjectQuery。
    heartQuery=[[HKAnchoredObjectQuery alloc]initWithType:对象谓词:谓词锚定:0限制:0结果处理程序:^(HKAnchoredObjectQuery*查询,NSArray*样本对象,NSArray*删除对象,HKQueryAnchor*新锚定,NSError*错误){
    如果(!error&&sampleObjects.count>0){
    HKQuantitySample*样本=(HKQuantitySample*)[sampleObjects对象索引:0];
    HKQUOTE*数量=样本数量;
    NSLog(@“%f”,[quantity doubleValueForUnit:[HKUnitFromString:@“count/min”]]);
    }否则{
    NSLog(@“查询%@”,错误);
    }
    }];
    //等等,还没结束,这是更新处理程序
    [heartQuery setUpdateHandler:^(HKAnchoredObjectQuery*查询,NSArray*样本数组,NSArray*删除对象,HKQueryAnchor*锚,NSError*错误){
    如果(!error&&SampleArray.con)