HealthKit:每日平均心率
HealthKit: Daily Heart Rate Average
我正在尝试从用户的设备获取每天的平均心率。我有下面的代码,它在调用时打印 "avgHeart",但不执行任何其他操作。
我自己测试phone肯定有心率数据,并且已经授权读取心率数据
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 天的平均心率。
主要问题是您要求 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
.
我正在尝试从用户的设备获取每天的平均心率。我有下面的代码,它在调用时打印 "avgHeart",但不执行任何其他操作。
我自己测试phone肯定有心率数据,并且已经授权读取心率数据
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 天的平均心率。
主要问题是您要求 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
.