从 HealthKit 查询更新 SwiftUI
Posted
技术标签:
【中文标题】从 HealthKit 查询更新 SwiftUI【英文标题】:Updating SwiftUI from HealthKit Query 【发布时间】:2021-05-09 13:22:12 【问题描述】:我想在 SwiftUI 中通过 ContentView 输出变量“healthStore.valueTest”。
类 healthStore 的结构如下:
class HealthStore
var healthStore: HKHealthStore?
var query: HKStatisticsQuery?
var valueTest: HKQuantity?
init()
if HKHealthStore.isHealthDataAvailable()
healthStore = HKHealthStore()
func calculateBloodPressureSystolic()
guard let bloodPressureSystolic = HKObjectType.quantityType(forIdentifier: .bloodPressureSystolic) else
// This should never fail when using a defined constant.
fatalError("*** Unable to get the bloodPressure count ***")
// 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)
query = HKStatisticsQuery(quantityType: bloodPressureSystolic,
quantitySamplePredicate: nil,
options: .discreteAverage)
query, statistics, error in
DispatchQueue.main.async
self.valueTest = statistics?.averageQuantity()
healthStore!.execute(query!)
ContentView 构建如下:
import SwiftUI
import HealthKit
struct ContentView: View
private var healthStore: HealthStore?
init()
healthStore = HealthStore()
var body: some View
Text("Hello, world!")
.padding().onAppear()
if let healthStore = healthStore
healthStore.requestAuthorization success in
if success
healthStore.calculateBloodPressureSystolic()
print(healthStore.query)
print(healthStore.valueTest)
struct ContentView_Previews: PreviewProvider
static var previews: some View
ContentView()
变量 self.valueTest 的值在进程 DispatchQueue.main.async 中分配。尽管如此,当通过 ContentView 查询时,我只得到一个 nil。
【问题讨论】:
【参考方案1】:您可以设置您的HealthStore
类并将其用作环境对象。假设您的应用使用 SwiftUI 生命周期,您可以在应用的 @main 入口点将 HealthStore 注入到环境中。
import SwiftUI
@main
struct NameOfYourHeathApp: App
let healthStore = HealthStore()
var body: some Scene
WindowGroup
ContentView()
.environmentObject(healthStore)
将您的 HealthStore
类更改为此。 (我在下面的示例中删除了您注释掉的代码)
import HealthKit
class HealthStore: ObservableObject
var healthStore: HKHealthStore?
var query: HKStatisticsQuery?
var valueTest: HKQuantity?
init()
if HKHealthStore.isHealthDataAvailable()
healthStore = HKHealthStore()
// I moved the HealthStore conditional check out of your View logic
// and placed it here instead.
func setUpHealthStore()
let typesToRead: Set = [
HKQuantityType.quantityType(forIdentifier: .bloodPressureSystolic)!
]
// I left the `toShare` as nil as I did not dig into adding bloodpressure reading to HealthKit.
healthStore?.requestAuthorization(toShare: nil, read: typesToRead, completion: success, error in
if success
self.calculateBloodPressureSystolic()
)
func calculateBloodPressureSystolic()
guard let bloodPressureSystolic = HKObjectType.quantityType(forIdentifier: .bloodPressureSystolic) else
// This should never fail when using a defined constant.
fatalError("*** Unable to get the bloodPressure count ***")
query = HKStatisticsQuery(quantityType: bloodPressureSystolic,
quantitySamplePredicate: nil,
options: .discreteAverage)
query, statistics, error in
DispatchQueue.main.async
self.valueTest = statistics?.averageQuantity()
healthStore!.execute(query!)
然后像这样在你的ContentView
中使用它。
import SwiftUI
struct ContentView: View
@EnvironmentObject var healthStore: HealthStore
var body: some View
Text("Hello, world!")
.onAppear
healthStore.setUpHealthStore()
我没有在 .plist 文件中设置适当的权限,但您还需要设置健康共享使用说明和健康更新使用说明。我假设您已经这样做了,但我只是想提一下。
【讨论】:
当我在控制台打印变量 healthStore.valueTest 时,我只得到一个 nil。以上是关于从 HealthKit 查询更新 SwiftUI的主要内容,如果未能解决你的问题,请参考以下文章