ios - 如何从 HealthKit 中获取与 Health App 值相同的静息能量值?

标签 ios swift healthkit

我正在使用苹果的 HealthKit sample但是,iPhone 中健康应用 中显示的静息能量 值与示例应用中获取的值不匹配。

根据苹果文档,HKQuantityTypeIdentifierBasalEnergyBurned 代表静息能量,所以我从 HealthKit 中获取了这个值,但我收到的值与静息能量不匹配健康应用中显示的能量

所以我遇到了苹果的 HealthKit sample他们根据公式计算静息能量:

// Calculates the user's total basal (resting) energy burn based off of their height, weight, age,
    // and biological sex. If there is not enough information, return an error.
    private func fetchTotalBasalBurn(completion: @escaping (HKQuantity?, Error?) -> Void)
    {
        let todayPredicate: NSPredicate = self.predicateForSamplesToday()

        let weightType = HKQuantityType.quantityType(forIdentifier: HKQuantityTypeIdentifier.bodyMass)!
        let heightType = HKQuantityType.quantityType(forIdentifier: HKQuantityTypeIdentifier.height)!

        let queryWeigth: HKCompletionHandle = {
            (weight, error) -> Void in

            guard let weight = weight else {
                completion(nil, error)

                return
            }

            let queryHeigth: HKCompletionHandle = {
                (height, error) -> Void in

                if height == nil {
                    completion(nil, error)

                    return;
                }

                var dateOfBirth: Date!

                do {

                    dateOfBirth = try self.healthStore!.dateOfBirth()

                } catch {

                    completion(nil, error)

                    return
                }

                var biologicalSexObjet: HKBiologicalSexObject!

                do {

                    biologicalSexObjet = try self.healthStore!.biologicalSex()

                } catch {

                    completion(nil, error)

                    return
                }

                // Once we have pulled all of the information without errors, calculate the user's total basal energy burn
                let basalEnergyButn: HKQuantity? = self.calculateBasalBurnTodayFromWeight(weight, height: height, dateOfBirth: dateOfBirth!, biologicalSex: biologicalSexObjet)

                completion(basalEnergyButn, nil)
            }

            if let healthStore = self.healthStore {

                healthStore.mostRecentQuantitySample(ofType: heightType, predicate: todayPredicate, completion: queryHeigth)
            }
        }

        if let healthStore = self.healthStore {
            healthStore.mostRecentQuantitySample(ofType: weightType, predicate: nil, completion: queryWeigth)
        }
    }

    private func calculateBasalBurnTodayFromWeight(_ weight: HKQuantity?, height: HKQuantity?, dateOfBirth: Date, biologicalSex: HKBiologicalSexObject) -> HKQuantity?
    {
        // Only calculate Basal Metabolic Rate (BMR) if we have enough information about the user
        guard let weight = weight, let height = height else {

            return nil
        }

        // Note the difference between calling +unitFromString: vs creating a unit from a string with
        // a given prefix. Both of these are equally valid, however one may be more convenient for a given
        // use case.
        let heightInCentimeters: Double = height.doubleValue(for: HKUnit(from:"cm"))
        let weightInKilograms: Double = weight.doubleValue(for: HKUnit.gramUnit(with: HKMetricPrefix.kilo))

        let nowDate = Date()
        let ageComponents: DateComponents = Calendar.current.dateComponents([Calendar.Component.year], from: dateOfBirth, to: nowDate)
        let ageInYears: Int = ageComponents.year!

        // BMR is calculated in kilocalories per day.
        let BMR: Double = self.calculateBMRFromWeight(weightInKilograms: weightInKilograms, height: heightInCentimeters, age: ageInYears, biologicalSex: biologicalSex.biologicalSex)

        // Figure out how much of today has completed so we know how many kilocalories the user has burned.
        let (startOfToday, endOfToday): (Date, Date) = self.datesFromToday()

        let secondsInDay: TimeInterval = endOfToday.timeIntervalSince(startOfToday)
        let percentOfDayComplete: Double = nowDate.timeIntervalSince(startOfToday) / secondsInDay

        let kilocaloriesBurned: Double = BMR * percentOfDayComplete

        let basalBurn = HKQuantity(unit: HKUnit.kilocalorie(), doubleValue: kilocaloriesBurned)

        return basalBurn
    }

/// Returns BMR value in kilocalories per day. Note that there are different ways of calculating the
    /// BMR. In this example we chose an arbitrary function to calculate BMR based on weight, height, age,
    /// and biological sex.
    private func calculateBMRFromWeight(weightInKilograms: Double, height heightInCentimeters: Double, age ageInYears: Int, biologicalSex: HKBiologicalSex) -> Double
    {
        var BMR: Double = 0

        if biologicalSex == .male {
            BMR = 66.0 + (13.8 * weightInKilograms) + (5.0 * heightInCentimeters) - (6.8 * Double(ageInYears))

            return BMR
        }

        BMR = 655 + (9.6 * weightInKilograms) + (1.8 * heightInCentimeters) - (4.7 * Double(ageInYears))

        return BMR
    }

我已尝试使用示例应用程序获取静息能量,但健康应用程序和示例应用程序中显示的静息能量值仍然不同。

谁能告诉我如何获取静息能量或者健康应用使用什么计算来找到静息能量

如果有人能给我一些建议就太好了,我是 HealthKit 的新手。

谢谢。

最佳答案

Apple 的样本似乎已经过时了。从 iOS 8 和 watchOS 2 开始,有一个调用来以与检索事件卡路里相同的方式检索此信息;只需更改标识符。 Apple Documentation

HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.basalEnergyBurned)

不要忘记包含读取此数据的额外权限。

关于ios - 如何从 HealthKit 中获取与 Health App 值相同的静息能量值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50003294/

相关文章:

ios - 在 UIColor 子类中设置属性时崩溃

javascript - 兼容 iOS 和常规浏览器的 JS 库(带拖放功能)

ios - Swift 中的数组扩展,使用 NSPropertyListReadOptions 从 plist 读取数组

angular - 为什么 Ionic Framework 插件 healthkit 出现错误 plugin_not_installed?

ios - 如何获取以前日期的 HealthKit 总步数

iphone - UITableView 延迟加载问题

ios - SKSpriteNode 的缓出动画

ios - 尺寸等级自动布局 : Constraint Activated For Wrong Size Class

html - iOS - Swift 如何在 UILabel 中点击链接

swift - watch 屏幕关闭时,Complication 能否访问 Healthkit?