【问题标题】:Why is m view not updating using ObservedObject and HealthKit?为什么 m 视图不使用 ObservedObject 和 HealthKit 进行更新?
【发布时间】:2023-01-24 01:38:45
【问题描述】:

在我的应用程序的主屏幕中,我有一个包含用户步骤的 Capsule()。这些数据是通过 HealthKit 获得的。数据是正确的,但是当它在健康应用程序中发生变化时,它应该在我的应用程序中发生变化,但这并没有发生。我如何获取'steps'变量来监听HealthKit,我的代码中一定有错误。

这是我的主页视图的代码:

import SwiftUI
import HealthKit

struct Home: View {
        
    @ObservedObject var healthStore = HealthStore()
    @State private var steps: [Step] = [Step]()

    init() {
        healthStore = HealthStore()
    }
    
    private func updateUIFromStatistics(_ statisticsCollection: HKStatisticsCollection) {
        
        let startDate = Date()
        let endDate = Date()
        
        statisticsCollection.enumerateStatistics(from: startDate, to: endDate) { (statistics, stop) in
            
            let count = statistics.sumQuantity()?.doubleValue(for: .count())
            let step = Step(count: Int(count ?? 0), date: statistics.startDate)
            steps.append(step)
        }
    }
    
    var body: some View {
        
        NavigationView {
        
        ScrollView {
            
            ZStack {
                Color("BackgroundColour")
                    .ignoresSafeArea()
                
                    VStack {
                        let totalSteps = steps.reduce(0) { $0 + $1.count }
                        ForEach($steps, id: \.id) { step in
                            Button(action: {
                                // Perform button action here
                                print("Step Capsule Tapped...")
                            }) {
                                HStack {
                                    Image("footsteps")

                                    Text("\(totalSteps)")
                                }
                            }
                        } // ForEach End
                    } // VStack End
            }//ZStack End
            .edgesIgnoringSafeArea(.all)
        } // ScrollView End
        .background(Color("BackgroundColour"))
        .onLoad {
            healthStore.requestAuthorization { success in
                if success {
                    healthStore.calculateSteps { statisticsCollection in
                        if let statisticsCollection = statisticsCollection {
                            // update the UI
                            updateUIFromStatistics(statisticsCollection)
                        }
                    }
                }
            }
        } // .onLoad End
        .onAppear(perform: {
            let defaults = UserDefaults.standard
            let keyString: String? = defaults.string(forKey: "key") ?? ""
            print("User's Key:\(keyString ?? "")")
        }) // .onAppear End
        } // NavigationView End
    }
}

HealthStore 的代码如下:

import Foundation
import HealthKit
import SwiftUI
import Combine


class HealthStore: ObservableObject {
    
    @Published var healthStore: HKHealthStore?
    @Published var query: HKStatisticsCollectionQuery?
    
    init() {
        if HKHealthStore.isHealthDataAvailable() {
            healthStore = HKHealthStore()
            
        }
    }

    func calculateSteps(completion: @escaping (HKStatisticsCollection?)-> Void) {
        
        let stepType = HKQuantityType.quantityType(forIdentifier: HKQuantityTypeIdentifier.stepCount)!
        let startDate = Calendar.current.date(byAdding: .day, value: -7, to: Date())
        let anchorDate = Date.mondayAt12AM()
        let daily = DateComponents(day: 1)
        let predicate = HKQuery.predicateForSamples(withStart: startDate, end: Date(), options: .strictStartDate)
        let compoundPredicate = NSCompoundPredicate(andPredicateWithSubpredicates:
                                    [.init(format: "metadata.%K != YES", HKMetadataKeyWasUserEntered), predicate]
                                )
        query = HKStatisticsCollectionQuery(
           quantityType: stepType,
           quantitySamplePredicate: compoundPredicate,
           options: .cumulativeSum,
           anchorDate: anchorDate,
           intervalComponents: daily)

        query!.initialResultsHandler = { query, statisticsCollection, error in
            completion(statisticsCollection)
            
        }
        if let healthStore = healthStore, let query = self.query {
            healthStore.execute(query)
        }
    }
    func requestAuthorization(completion: @escaping (Bool) -> Void) {
        
        let stepType = HKQuantityType.quantityType(forIdentifier: HKQuantityTypeIdentifier.stepCount)!
        
        guard let healthStore = self.healthStore else { return completion(false) }
        
        healthStore.requestAuthorization(toShare: [], read: [stepType]) { (success, error) in
            completion(success)
        }
    }
}

extension Date {
    static func mondayAt12AM() -> Date {
        return Calendar(identifier: .iso8601).date(from: Calendar(identifier: .iso8601).dateComponents([.yearForWeekOfYear, .weekOfYear], from: Date()))!
    }
}

这是步骤的代码:

import Foundation

struct Step: Identifiable {
    let id = UUID()
    let count: Int
    let date: Date
}

下面是 Home 视图中使用的 .onLoad 方法的代码:

import SwiftUI

struct ViewDidLoadModifier: ViewModifier {

    @State private var didLoad = false
    private let action: (() -> Void)?

    init(perform action: (() -> Void)? = nil) {
        self.action = action
    }

    func body(content: Content) -> some View {
        content.onAppear {
            if didLoad == false {
                didLoad = true
                action?()
            }
        }
    }
}

extension View {

    func onLoad(perform action: (() -> Void)? = nil) -> some View {
        modifier(ViewDidLoadModifier(perform: action))
    }

}

有任何想法吗?

【问题讨论】:

  • 您在 Home 中两次初始化 healthStore,可能与您的问题无关,但仍然是您应该解决的问题。

标签: ios swift swiftui healthkit


【解决方案1】:

我想我知道这里缺少什么。

在你的类HealthStore中,在方法@​​987654323@中,你已经设置了你的HKStatisticsCollectionQueryinitialResultsHandler属性。但是,您尚未设置 statisticsUpdateHandler 属性。

要继续监听来自HealthKit的更新,在initialResultsHandler完成执行后,还需要设置statisticsUpdateHandler

根据statisticsUpdateHandler documentation,万一statisticsUpdateHandler为零,即上述情况,HKStatisticsCollectionQuery将:

“完成初始结果计算后自动停止”

这似乎与您所观察到的一致。

完全披露,我从未使用过 HealthKit,所以如果这没有帮助请原谅我。在查看了您的代码并在此处写下了我突然想到的内容后,我已经阅读了 HealthKit 文档。

如果它确实对您有帮助,请考虑将其标记为答案。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-21
    • 1970-01-01
    • 1970-01-01
    • 2020-05-02
    • 1970-01-01
    • 2020-07-12
    相关资源
    最近更新 更多