swift 如何修复使用HealthKit时显示的图表数据?

zfciruhq  于 2023-06-04  发布在  Swift
关注(0)|答案(1)|浏览(167)

从HealthKit阅读数据时,我的图表数据出现问题。我正在使用一个长时间运行的查询和一个更新处理程序来在后台添加新的数据/值。然而,每当我关闭和打开应用程序时,我的图表数据似乎都在重新绘制,这使得线条变得疯狂。我下面的列表也得到了额外的重复值。我尝试通过使用.onDisappear修饰符停止查询来修复此问题,但.onDisappear不会更新值,除非我强制关闭应用程序并再次打开它。

//Properties within my view model for resting HR.
var restingHRquery: HKStatisticsCollectionQuery?
@Published var restingHR: [RestingHeartRate] = [RestingHeartRate]()

    func calculateRestingHRData() {
        
        let restingHRpredicate = HKQuery.predicateForSamples(withStart: oneWeekAgo, end: nil, options: .strictStartDate)
        
        
        restingHRquery =   HKStatisticsCollectionQuery(quantityType: restingHeartRateType,
                                                       quantitySamplePredicate: restingHRpredicate,
                                                       options: .discreteAverage,
                                                       anchorDate: anchorDate,
                                                       intervalComponents: daily)
        
        
        restingHRquery!.initialResultsHandler = {
            restingQuery, statisticsCollection, error in
            
            //Handle errors here
            if let error = error as? HKError {
                switch (error.code) {
                case .errorHealthDataUnavailable:
                    return
                case .errorNoData:
                    return
                default:
                    return
                }
            }
            
            guard let statisticsCollection = statisticsCollection else { return}
            
            //Calculating resting HR
            statisticsCollection.enumerateStatistics(from: self.startDate, to: self.date) { statistics, stop in
                if let restHRquantity = statistics.averageQuantity() {
                    let hrdate = statistics.startDate
                    
                    //HR Units
                    let hrUnit = HKUnit(from: "count/min")
                    let restHRvalue = restHRquantity.doubleValue(for: hrUnit)
                    let restHR = RestingHeartRate(restingValue: Int(restHRvalue), date: hrdate)
                    
                    DispatchQueue.main.async {
                        self.restingHR.append(restHR)
                    }
                }
            }
        }
        
        restingHRquery!.statisticsUpdateHandler = {
            restingQuery, statistics, statisticsCollection, error in
            
            //Handle errors here
            if let error = error as? HKError {
                switch (error.code) {
                case .errorHealthDataUnavailable:
                    return
                case .errorNoData:
                    return
                default:
                    return
                }
            }
            
            guard let statisticsCollection = statisticsCollection else { return}
            
            //Calculating resting HR
            statisticsCollection.enumerateStatistics(from: self.startDate, to: self.date) { statistics, stop in
                if let restHRquantity = statistics.averageQuantity() {
                    let hrdate = statistics.startDate
                    
                    //HR Units
                    let hrUnit = HKUnit(from: "count/min")
                    let restHRvalue = restHRquantity.doubleValue(for: hrUnit)
                    let restHR = RestingHeartRate(restingValue: Int(restHRvalue), date: hrdate)
                    
                    DispatchQueue.main.async {
                        self.restingHR.append(restHR)
                    }
                }
            }
        }
        
        
        guard let restingHRquery = self.restingHRquery else { return }
      
        self.healthStore?.execute(restingHRquery)
    }
struct OneWeekRestHRChartView: View {
    @EnvironmentObject var healthStoreVM: HealthStoreViewModel
    
    var body: some View {
        
        VStack(alignment: .leading, spacing: 10) {
      
            Text("Average: \(healthStoreVM.averageRestHR) bpm")
                .font(.headline)
            
            Chart {
                ForEach(healthStoreVM.restingHR.reversed(), id: \.date) {
                    restHrData in
                    
                    LineMark(x: .value("day", restHrData.date, unit: .day),
                             y: .value("RHR", restHrData.restingValue)
                    )
                    .interpolationMethod(.catmullRom)
                    .foregroundStyle(.red)
                    .symbol() {
                        Circle()
                            .fill(.red)
                            .frame(width: 15)
                    }
                }
            }
            .frame(height: 200)
            .chartYScale(domain: 30...80)
            .chartXAxis {
                AxisMarks(values: .stride(by: .day)) {
                    AxisGridLine()
                    AxisValueLabel(format: .dateTime.day().month(), centered: true)
                    
                }
            }
        }
        .padding(.horizontal)
        .navigationTitle("Resting Heart Rate")

        
        List{
            ForEach(healthStoreVM.restingHR.reversed(), id: \.date) {
                restHR in
                
                DataListView(imageText: "heart.fill",
                             imageColor: .red,
                             valueText: "\(restHR.restingValue) bpm",
                             date: restHR.date)
            }
        }
        .listStyle(.inset)
    }
}

这可能只是SwiftUI图表问题吗?

rsaldnfx

rsaldnfx1#

statisticsUpdateHandler不会仅使用新结果调用。调用它时会显示更新后的完整结果集。
在再次添加结果之前,需要从restingHR中清除现有结果。

restingHRquery!.statisticsUpdateHandler = {
            restingQuery, statistics, statisticsCollection, error in
            
            //Handle errors here
            if let error = error as? HKError {
                switch (error.code) {
                case .errorHealthDataUnavailable:
                    return
                case .errorNoData:
                    return
                default:
                    return
                }
            }
            
            guard let statisticsCollection = statisticsCollection else { return}

            DispatchQueue.main.async {

                self.restingHR.removeAll()
            
            //Calculating resting HR
                statisticsCollection.enumerateStatistics(from: self.startDate, to: self.date) { statistics, stop in
                    if let restHRquantity = statistics.averageQuantity() {
                        let hrdate = statistics.startDate
                    
                        //HR Units
                        let hrUnit = HKUnit(from: "count/min")
                        let restHRvalue = restHRquantity.doubleValue(for: hrUnit)
                        let restHR = RestingHeartRate(restingValue: Int(restHRvalue), date: hrdate)
                    
                        self.restingHR.append(restHR)
                    }
                }
            }
        }

相关问题