Swift:将数据从一个类发布到另一个类不工作(Apple HealthKit)



classHealthKitQueryBuilder

import Foundation
import HealthKit
class HealthKitQueryBuilder:ObservableObject {

let healthStore: HKHealthStore
let dateFormatter = DateFormatter()

@Published var hourlyStpCount: [HealthData]?

init(healthStore: HKHealthStore) {
self.healthStore = healthStore
}
func readHourlyStepCount(){
dateFormatter.dateFormat = "yyyy-MM-dd hh:mm:ss"
var hourlyStepCount = [HealthData]()
guard let stepCountType = HKObjectType.quantityType(forIdentifier: .stepCount) else {
fatalError("*** Unable to get the step count type ***")
}
var interval = DateComponents()
interval.hour = 1
let calendar = Calendar.current
let anchorDate = calendar.date(bySettingHour: 0, minute: 55, second: 0, of: Date())
let query = HKStatisticsCollectionQuery.init(quantityType: stepCountType,
quantitySamplePredicate: nil,
options: .cumulativeSum,
anchorDate: anchorDate!,
intervalComponents: interval)
query.initialResultsHandler = { query, results, error in
let startDate = calendar.date(byAdding: .hour,value: -24, to: Date())
DispatchQueue.main.async {
results?.enumerateStatistics(from: startDate!,to: Date(), with: { (result, stop) in
hourlyStepCount.append(HealthData(unit: "count", startDate: self.dateFormatter.string(from: result.startDate) , endDate: self.dateFormatter.string(from: result.endDate), value: (result.sumQuantity()?.doubleValue(for: HKUnit.count()) ?? 0)))

})
print("Hourly step count : (hourlyStepCount)")
self.hourlyStpCount = hourlyStepCount
}
}
healthStore.execute(query)
}
}

DataPointsJSONBuilder

import Foundation
import HealthKit
import SwiftUI
class DataPointsJSONBuilder {

let healthStore: HKHealthStore
@ObservedObject var queryBuilder: HealthKitQueryBuilder

init(healthStore: HKHealthStore) {
self.healthStore = healthStore
self.queryBuilder = HealthKitQueryBuilder(healthStore: healthStore)
}

func createJSON() ->String?{
queryBuilder.readHourlyStepCount()
let totalStepCount = queryBuilder.hourlyStpCount
let averageRestingHeartRate = [HealthData(unit: "count", startDate: "2022-11-22 10:55:00 PM +0000", endDate: "2022-11-22 11:55:00 PM +0000", value: 100.0)]
let averageHeartRateVariability = [HealthData(unit: "count", startDate: "2022-11-22 10:55:00 PM +0000", endDate: "2022-11-22 11:55:00 PM +0000", value: 100.0)]
let averageRespiratoryRate = [HealthData(unit: "count", startDate: "2022-11-22 10:55:00 PM +0000", endDate: "2022-11-22 11:55:00 PM +0000", value: 100.0)]
let totalSleepDuration = [HealthData(unit: "count", startDate: "2022-11-22 10:55:00 PM +0000", endDate: "2022-11-22 11:55:00 PM +0000", value: 100.0)]
let heartRate = [HealthData(unit: "count", startDate: "2022-11-22 10:55:00 PM +0000", endDate: "2022-11-22 11:55:00 PM +0000", value: 100.0)]
let systolicBloodPressure = [HealthData(unit: "count", startDate: "2022-11-22 10:55:00 PM +0000", endDate: "2022-11-22 11:55:00 PM +0000", value: 100.0)]
let diastolicBloodPressure = [HealthData(unit: "count", startDate: "2022-11-22 10:55:00 PM +0000", endDate: "2022-11-22 11:55:00 PM +0000", value: 100.0)]
let oxygenSaturation = [HealthData(unit: "count", startDate: "2022-11-22 10:55:00 PM +0000", endDate: "2022-11-22 11:55:00 PM +0000", value: 100.0)]
let currentGlucose = [HealthData(unit: "count", startDate: "2022-11-22 10:55:00 PM +0000", endDate: "2022-11-22 11:55:00 PM +0000", value: 100.0)]
let averageGlucose = [HealthData(unit: "count", startDate: "2022-11-22 10:55:00 PM +0000", endDate: "2022-11-22 11:55:00 PM +0000", value: 100.0)]

let dataPoints = DataPointsObj(totalStepCount: totalStepCount, averageRestingHeartRate: [], averaHeartRatevariability: [], averageRespiratoryRate: [], totalSleepDuration: [], heartRate: [], systolicBloodPressure: [], diastolicBloodPressure: [], oxygenSaturation: [], currentGlucoseValue: [], averageGlucoseValue: [])

guard let JSON = encodeToJSON(dataPointsObj: dataPoints) else {
return nil
}
return JSON
}

private func encodeToJSON(dataPointsObj: DataPointsObj) -> String? {
let encoder = JSONEncoder()
encoder.outputFormatting = .withoutEscapingSlashes
do {
let result = try encoder.encode(dataPointsObj)
if let jsonString = String(data: result, encoding: .utf8){
return jsonString
}
return nil
} catch {
return nil
}
}
}

我有以上2类实现从苹果健康工具包读取数据,并使json对象发送到后端。但是在获取数据之后,数据没有发布到DataPointsJSONBuilder类。我成功地在HealthKitQueryBuilder类中打印了数据,现在我只添加了步骤计数的代码。我在UI的onAppear内部调用createJSON函数,如下所示。

.onAppear(){
print(DataPointsJSONBuilder(healthStore: healthStore).createJSON()!)
}

我想做的是从healthkit读取数据,并将它们带到DataPointsJSONBuilder类,通过REST api将其发送到后端。我不明白为什么我在读取数据时不更新hourlyStpCount。如果有一个错误的实现在这里,请纠正我或建议一个方法来解决我的问题。谢谢!

我想说这里的问题是您试图使用异步调用作为同步。

您使用

print(DataPointsJSONBuilder(healthStore: healthStore).createJSON()!)

createJSON()函数确实有返回值。相反,它应该采用异步方法。有许多方法可以实现这一点-您尝试使用一种,例如@Published功能-但为了简单起见,我将使用回调(完成处理程序)发布方法。

您需要更改一段相对较大的代码,但为了说明我的观点,在末尾应该是这样的:

func readHourlyStepCount(callback: ([HealthData]) -> ()) {
//implementation
callback(hourlyStepCount)
//...
}

在DataPointsJSONBuilder:

func createJSON(callback: (String?) -> ()) {
//implementation
callback(JSON)
//...
}

最后:

DataPointsJSONBuilder(healthStore: healthStore).createJSON { json in
print(json)
}

PS:也许你需要在回调中添加@escaping标签。

最新更新