此 HealthKit 错误的原因是啥:“将样本添加到锻炼时发生错误”?

Posted

技术标签:

【中文标题】此 HealthKit 错误的原因是啥:“将样本添加到锻炼时发生错误”?【英文标题】:What is the cause of this HealthKit error: "An error occurred while adding a sample to the workout"?此 HealthKit 错误的原因是什么:“将样本添加到锻炼时发生错误”? 【发布时间】:2015-03-16 01:04:20 【问题描述】:

我明白为什么,但 HealthKit 提出的错误的模棱两可完全是一个黑匣子。为什么会出现错误:

向锻炼添加样本时出错:操作无法完成。

我一直在网上搜索示例,但其中大多数都在 swift 中。 :(

这是我的代码:

- (NSSet *)dataTypesToRead 
    HKQuantityType *heartRate = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierHeartRate];

    return [NSSet setWithObjects:heartRate, nil];


- (NSSet *)dataTypesToWrite 
    HKWorkoutType* workout = [HKWorkoutType workoutType];
    HKQuantityType *energyBurnedType = [HKQuantityType  quantityTypeForIdentifier:HKQuantityTypeIdentifierActiveEnergyBurned];

    return [NSSet setWithObjects:workout, energyBurnedType, nil];


- (void)saveWorkout 

    HKHealthStore* healthStore = [[HKHealthStore alloc] init];

    NSDate* timeOfWorkout = [NSDate date];

    HKWorkoutType* type = [HKWorkoutType workoutType];

    [healthStore requestAuthorizationToShareTypes:[self dataTypesToWrite]
                                        readTypes:[self dataTypesToRead]
                                       completion:^(BOOL success, NSError *error) 

       if(success == YES)
       
           // This sample uses hard-coded values and performs all the operations inline
           // for simplicity's sake. A real-world app would calculate these values
           // from sensor data and break the operation up using helper methods.

           HKQuantity *energyBurned =
           [HKQuantity quantityWithUnit:[HKUnit kilocalorieUnit]
                            doubleValue:333.0];

           HKQuantity *distance =
           [HKQuantity quantityWithUnit:[HKUnit mileUnit]
                            doubleValue:0.0];

           // Provide summary information when creating the workout.
           HKWorkout *workout = [HKWorkout workoutWithActivityType:HKWorkoutActivityTypeTraditionalStrengthTraining
                                                         startDate:timeOfWorkout
                                                           endDate:timeOfWorkout
                                                          duration:0
                                                 totalEnergyBurned:energyBurned
                                                     totalDistance:distance
                                                          metadata:nil];

           // Save the workout before adding detailed samples.
           [healthStore saveObject:workout withCompletion:^(BOOL success, NSError *error) 
               if (!success) 
                   // Perform proper error handling here...
                   NSLog(@"*** An error occurred while saving the "
                         @"workout: %@ ***", error.localizedDescription);

                   abort();
               

           ];

           // Add optional, detailed information for each time interval
           NSMutableArray *samples = [NSMutableArray array];

           HKQuantityType *energyBurnedType =
           [HKObjectType quantityTypeForIdentifier:
            HKQuantityTypeIdentifierActiveEnergyBurned];


           [samples addObject:energyBurnedType];

           // Add all the samples to the workout.
           [healthStore
            addSamples:samples
            toWorkout:workout
            completion:^(BOOL success, NSError *error) 
                if (!success) 
                    // Perform proper error handling here...
                    NSLog(@"*** An error occurred while adding a "
                          @"sample to the workout: %@ ***",
                          error.localizedDescription);

                    abort();
                
            ];
       
       else
       
           // Determine if it was an error or if the
           // user just canceld the authorization request
       

   ];

【问题讨论】:

控制台中是否有任何消息或设备上的崩溃日志?当您从 Cocoa API 收到“操作无法完成”错误时,通常表明在与负责执行操作的系统守护进程通信时发生了某种故障。例如,在这种情况下,healthd 可能已经崩溃。 我得到的唯一控制台消息是:“*** 将样本添加到锻炼时发生错误:操作无法完成。(Cocoa 错误 4097。)***” 这很可能意味着 healthd 在响应您的请求时崩溃了。您应该找到 healthd 崩溃日志,然后向 Apple 提交错误:bugreporter.apple.com。 @tshortli,详细检查我的答案,崩溃是由于样本可变数组而发生的。其中包含一组 HKQuantityType 对象,但它应该是 HKQuantitySample 或 HKCategorySample。 【参考方案1】:

在这里我发现了 2 个问题,

    您在将锻炼保存到 HealthKit 之前尝试将样本添加到锻炼中。 Samples 数组应包含 HKQuantitySample 或 HKCategorySample 类型的对象。

这工作正常...

- (NSSet *)dataTypesToRead 
    HKQuantityType *heartRate = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierHeartRate];

    return [NSSet setWithObjects:heartRate, nil];


- (NSSet *)dataTypesToWrite 
    HKWorkoutType* workout = [HKWorkoutType workoutType];
    HKQuantityType *energyBurnedType = [HKQuantityType  quantityTypeForIdentifier:HKQuantityTypeIdentifierActiveEnergyBurned];

    return [NSSet setWithObjects:workout, energyBurnedType, nil];


- (void)saveWorkout 

    HKHealthStore* healthStore = [[HKHealthStore alloc] init];

    NSDate* timeOfWorkout = [NSDate date];

    [healthStore requestAuthorizationToShareTypes:[self dataTypesToWrite]
                                        readTypes:[self dataTypesToRead]
                                       completion:^(BOOL success, NSError *error) 

                                           if(success == YES)
                                           
                                               // This sample uses hard-coded values and performs all the operations inline
                                               // for simplicity's sake. A real-world app would calculate these values
                                               // from sensor data and break the operation up using helper methods.

                                               HKQuantity *energyBurned =
                                               [HKQuantity quantityWithUnit:[HKUnit kilocalorieUnit]
                                                                doubleValue:333.0];

                                               HKQuantity *distance =
                                               [HKQuantity quantityWithUnit:[HKUnit mileUnit]
                                                                doubleValue:0.0];

                                               // Provide summary information when creating the workout.
                                               HKWorkout *workout = [HKWorkout workoutWithActivityType:HKWorkoutActivityTypeTraditionalStrengthTraining
                                                                                             startDate:timeOfWorkout
                                                                                               endDate:timeOfWorkout
                                                                                              duration:0
                                                                                     totalEnergyBurned:energyBurned
                                                                                         totalDistance:distance
                                                                                              metadata:nil];

                                               // Save the workout before adding detailed samples.
                                               [healthStore saveObject:workout withCompletion:^(BOOL success, NSError *error) 
                                                   if (!success) 
                                                       // Perform proper error handling here...
                                                       NSLog(@"*** An error occurred while saving the "
                                                             @"workout: %@ ***", error.localizedDescription);

//                                                       abort();
                                                   
                                                   else
                                                   
                                                       // Add optional, detailed information for each time interval
                                                       NSMutableArray *samples = [NSMutableArray array];

                                                       HKQuantityType *energyBurnedType =
                                                       [HKObjectType quantityTypeForIdentifier:
                                                        HKQuantityTypeIdentifierActiveEnergyBurned];

                                                       HKQuantity *energyBurnedQuantity = [HKQuantity quantityWithUnit:[HKUnit kilocalorieUnit] doubleValue:334];

                                                       HKQuantitySample *energyBurnedSample = [HKQuantitySample quantitySampleWithType:energyBurnedType quantity:energyBurnedQuantity startDate:[NSDate date] endDate:[NSDate date]];

                                                       [samples addObject:energyBurnedSample];

                                                       // Add all the samples to the workout.
                                                       [healthStore
                                                        addSamples:samples
                                                        toWorkout:workout
                                                        completion:^(BOOL success, NSError *error) 
                                                            if (!success) 
                                                                // Perform proper error handling here...
                                                                NSLog(@"*** An error occurred while adding a "
                                                                      @"sample to the workout: %@ ***",
                                                                      error.localizedDescription);

                                                                //                                                        abort();
                                                            
                                                        ];

                                                   

                                               ];

                                           
                                           else
                                           
                                               // Determine if it was an error or if the
                                               // user just canceld the authorization request
                                           

                                       ];

【讨论】:

谢谢,我确实从样本中看到 HealthKit 中的“334”kcal,这正是我所需要的。一个问题,当 HKWorkout 对象是使用健身活动类型创建时,变量“energyBurned”作为参数包含在内,似乎没有使用。由于 HKSample 实际上提供 kcal,我可以将 nil 传递给此参数吗?如果不是,我该如何处理这些无关代码? @MattMiller,根据 Apple 的 HealthKit 设计理念,HKSample 是 HKQuantitySample 和 HKCategorySample 类的基类。 HKSample 的目的是存储要存储的样本类型,在我们的例子中它是“HKQuantityTypeIdentifierActiveEnergyBurned”。但是,HKSample 不能存储数据的测量(数量/类别)。 HKSample 的子类负责存储这些数据。甚至无法通过“init”方法实例化 HKSample。

以上是关于此 HealthKit 错误的原因是啥:“将样本添加到锻炼时发生错误”?的主要内容,如果未能解决你的问题,请参考以下文章

我在这里遇到的这个错误到底是啥? (iOS、Xcode、Healthkit)

我在这里遇到的这个错误到底是啥? (iOS、Xcode、Healthkit)

案例陈述中出现此错误的原因是啥

此 WCF 错误的原因可能是啥?

核心数据“数据库出现损坏”——导致此错误的原因是啥?

使用 HealthKit 检索 SleepAnalysis 后,我仍然收到此 Authorization Not Defined 错误