HealthKit:每日平均心率

时间:2019-02-22 13:35:14

标签: ios swift xcode health-kit

我正在尝试从用户的设备获取每天的平均心率。我有下面的代码,该代码在调用时会显示“ avgHeart”,但不会执行其他任何操作。

我正在自己的手机上对其进行测试,该手机肯定具有心律数据,并已被授权读取心律数据。

func fortnightAvgHeartRate() {
    print("avgHEART")
    let calendar = Calendar.current

    var interval = DateComponents()
    // 14-day time interval
    interval.day = 1

    // Set the anchor date to Monday at 3:00 a.m.
    let anchorDateTMP = calendar.date(byAdding: .day, value: -14, to: Date())!
    let anchorDate = calendar.date(bySettingHour: 0, minute: 0, second: 0, of: anchorDateTMP)!

    guard let quantityType = HKQuantityType.quantityType(forIdentifier: .heartRate) else {
        fatalError("*** Unable to create a step count type ***")
    }

    // Create the query
    let query = HKStatisticsCollectionQuery(quantityType: quantityType,
                                            quantitySamplePredicate: nil,
                                            options: .discreteAverage,
                                            anchorDate: anchorDate,
                                            intervalComponents: interval)

    // Set the results handler
    query.initialResultsHandler = {
        query, results, error in

        guard let statsCollection = results else {
            // Perform proper error handling here
            fatalError("*** An error occurred while calculating the statistics: \(error?.localizedDescription) ***")
        }

        let endDate = Date()

        guard let startDate = calendar.date(byAdding: .day, value: -14, to: endDate) else {
            fatalError("*** Unable to calculate the start date ***")
        }

        // Plot the weekly step counts over the past 3 months
        statsCollection.enumerateStatistics(from: startDate, to: endDate) { [unowned self] statistics, stop in

            if let quantity = statistics.sumQuantity() {
                let date = statistics.startDate
                let value = quantity.doubleValue(for: HKUnit.count())

                let formatter = DateFormatter()
                formatter.dateFormat = "ddMMMyyyy"
                let dateResult = formatter.string(from: date)

                print("HEART")
                self.addToArray(date: dateResult, value: value, number: 5)
            }
        }
    }

    HKHealthStore().execute(query)
}

被调用函数如下:

var dateArray: [String] = []
var avgHeartRateDataArray: [Double] = []

func addToArray(date: String, value: Double, number: Double) {
    // ...
    if number == 5 {
        avgHeartRateDataArray.append(value)
        print("avgHeartRate: \(avgHeartRateDataArray)")
    }

    if dateArray.contains(date) {
        // Do nothing
    } else {
        dateArray.append(date)
    }

    print("ARRAY1: \(dateArray)")
}

在此情况下,根本没有调用print("avgHeartRate: \(avgHeartRateDataArray)")

理想情况下,我希望在avgHeartRateData数组中填充过去14天的平均心率。

1 个答案:

答案 0 :(得分:1)

主要问题是您要输入statistics.sumQuantity(),此查询始终为nil。相反,您应该要求statistics.averageQuantity()

此外,quantity.doubleValue(for: HKUnit.count())将引发错误,因为心率不是存储在计数中,而是存储在每单位时间的计数中。要获取每分钟的节拍,请使用HKUnit.count().unitDivided(by: HKUnit.minute())

这将使您的代码正常工作,但实际上您还应该限制查询的日期。不要运行无限制的查询,然后将结果限制为适合您的日期范围,将谓词设置为仅获取所需的统计信息。

下面是一个示例,其中包含了我上面所说的所有内容:

func printFortnightAvgHeartRate() {
    let calendar = Calendar.current

    let heartRateType = HKQuantityType.quantityType(forIdentifier: .heartRate)!

    // Start 14 days back, end with today
    let endDate = Date()
    let startDate = calendar.date(byAdding: .day, value: -14, to: endDate)!

    let predicate = HKQuery.predicateForSamples(withStart: startDate, end: endDate, options: [])

    // Set the anchor to exactly midnight
    let anchorDate = calendar.date(bySettingHour: 0, minute: 0, second: 0, of: Date())!

    // Generate daily statistics
    var interval = DateComponents()
    interval.day = 1

    // Create the query
    let query = HKStatisticsCollectionQuery(quantityType: heartRateType,
                                            quantitySamplePredicate: predicate,
                                            options: .discreteAverage,
                                            anchorDate: anchorDate,
                                            intervalComponents: interval)

    // Set the results handler
    query.initialResultsHandler = { query, results, error in
        guard let statsCollection = results else { return }

        for statistics in statsCollection.statistics() {
            guard let quantity = statistics.averageQuantity() else { continue }

            let beatsPerMinuteUnit = HKUnit.count().unitDivided(by: HKUnit.minute())
            let value = quantity.doubleValue(for: beatsPerMinuteUnit)

            let df = DateFormatter()
            df.dateStyle = .medium
            df.timeStyle = .none
            print("On \(df.string(from: statistics.startDate)) the average heart rate was \(value) beats per minute")
        }
    }

    HKHealthStore().execute(query)
}

另外,在addToArray函数中,您似乎在使用number参数来区分数据类型。至少为此使用Int,而不是Double,但理想情况下应该是enum