无法使用锚定查询获取重量样本
Can't get weight samples using anchored query
我正在开发 watchOS 应用程序,这是我的第一个 Swift/iOS 项目。我想获取最新的体重样本并将其用于一些计算。结果呈现给用户。一旦添加了新示例,我也想更新我的 UI。它在全新的模拟器安装中工作。只要我在 iOS 模拟器中添加示例,应用程序就会在 watchOS 模拟器中更新其 UI。但是,它在我的真实设备上或重置 watchOS 模拟器后不起作用。我只是不知道为什么。 HKAnchoredObjectQuery
只是 returns 0
个样本,但我肯定有一些样本存储在健康中。我什至可以在手表上的 Settings > Health
下看到它们。我无法想象这与我的代码有关,但它是:
class WeightProvider: ObservableObject {
private static let weightSampleType = HKSampleType.quantityType(forIdentifier: .bodyMass)!
private static let healthStore: HKHealthStore = .init()
private var previousAnchor: HKQueryAnchor?
private var runningQuery: HKAnchoredObjectQuery?
@Published var bodyWeight: Measurement<UnitMass>?
func getBodyWeight(longRunning: Bool = false) {
let query = HKAnchoredObjectQuery(type: Self.weightSampleType, predicate: nil, anchor: previousAnchor, limit: longRunning ? HKObjectQueryNoLimit : 1, resultsHandler: processQueryResult)
if longRunning {
query.updateHandler = processQueryResult
runningQuery = query
}
Self.healthStore.execute(query)
}
func stopLongRunningQuery() {
if let runningQuery = runningQuery {
Self.healthStore.stop(runningQuery)
self.runningQuery = nil
}
}
private func processQueryResult(_: HKAnchoredObjectQuery, samples: [HKSample]?, _: [HKDeletedObject]?, newAnchor: HKQueryAnchor?, error: Error?) {
guard let samples = samples as? [HKQuantitySample], error == nil else {
fatalError(error?.localizedDescription ?? "Failed to cast [HKSample] to [HKQuantitySample]")
}
previousAnchor = newAnchor
guard let sample = samples.last else {
return
}
DispatchQueue.main.async {
if Locale.current.usesMetricSystem {
let weight = sample.quantity.doubleValue(for: .gramUnit(with: .kilo))
self.bodyWeight = .init(value: weight, unit: UnitMass.kilograms)
} else {
let weight = sample.quantity.doubleValue(for: .pound())
self.bodyWeight = .init(value: weight, unit: UnitMass.pounds)
}
}
}
}
// MARK: - HealthKit Authorization
extension WeightProvider {
private static let typesToRead: Set<HKObjectType> = [
weightSampleType,
]
func authorize(completion: @escaping (Bool, Error?) -> Swift.Void) {
Self.healthStore.requestAuthorization(toShare: nil, read: Self.typesToRead) { success, error in
completion(success, error)
}
}
}
在我的观点中 onAppear
我调用这个函数:
private func authorizeHealthKit() {
guard firstRun else {
return
}
firstRun = false
weightProvider.authorize { success, error in
guard success, error == nil else {
return
}
weightProvider.getBodyWeight(longRunning: true)
}
}
正如我在手表的设置中看到的那样,HealthKit 已获得适当授权。有任何想法吗?一般对我的代码有什么提示吗?
哇,毕竟这次我发现了问题:行 previousAnchor = newAnchor
需要在 之后 guard
语句。就是这样。
我正在开发 watchOS 应用程序,这是我的第一个 Swift/iOS 项目。我想获取最新的体重样本并将其用于一些计算。结果呈现给用户。一旦添加了新示例,我也想更新我的 UI。它在全新的模拟器安装中工作。只要我在 iOS 模拟器中添加示例,应用程序就会在 watchOS 模拟器中更新其 UI。但是,它在我的真实设备上或重置 watchOS 模拟器后不起作用。我只是不知道为什么。 HKAnchoredObjectQuery
只是 returns 0
个样本,但我肯定有一些样本存储在健康中。我什至可以在手表上的 Settings > Health
下看到它们。我无法想象这与我的代码有关,但它是:
class WeightProvider: ObservableObject {
private static let weightSampleType = HKSampleType.quantityType(forIdentifier: .bodyMass)!
private static let healthStore: HKHealthStore = .init()
private var previousAnchor: HKQueryAnchor?
private var runningQuery: HKAnchoredObjectQuery?
@Published var bodyWeight: Measurement<UnitMass>?
func getBodyWeight(longRunning: Bool = false) {
let query = HKAnchoredObjectQuery(type: Self.weightSampleType, predicate: nil, anchor: previousAnchor, limit: longRunning ? HKObjectQueryNoLimit : 1, resultsHandler: processQueryResult)
if longRunning {
query.updateHandler = processQueryResult
runningQuery = query
}
Self.healthStore.execute(query)
}
func stopLongRunningQuery() {
if let runningQuery = runningQuery {
Self.healthStore.stop(runningQuery)
self.runningQuery = nil
}
}
private func processQueryResult(_: HKAnchoredObjectQuery, samples: [HKSample]?, _: [HKDeletedObject]?, newAnchor: HKQueryAnchor?, error: Error?) {
guard let samples = samples as? [HKQuantitySample], error == nil else {
fatalError(error?.localizedDescription ?? "Failed to cast [HKSample] to [HKQuantitySample]")
}
previousAnchor = newAnchor
guard let sample = samples.last else {
return
}
DispatchQueue.main.async {
if Locale.current.usesMetricSystem {
let weight = sample.quantity.doubleValue(for: .gramUnit(with: .kilo))
self.bodyWeight = .init(value: weight, unit: UnitMass.kilograms)
} else {
let weight = sample.quantity.doubleValue(for: .pound())
self.bodyWeight = .init(value: weight, unit: UnitMass.pounds)
}
}
}
}
// MARK: - HealthKit Authorization
extension WeightProvider {
private static let typesToRead: Set<HKObjectType> = [
weightSampleType,
]
func authorize(completion: @escaping (Bool, Error?) -> Swift.Void) {
Self.healthStore.requestAuthorization(toShare: nil, read: Self.typesToRead) { success, error in
completion(success, error)
}
}
}
在我的观点中 onAppear
我调用这个函数:
private func authorizeHealthKit() {
guard firstRun else {
return
}
firstRun = false
weightProvider.authorize { success, error in
guard success, error == nil else {
return
}
weightProvider.getBodyWeight(longRunning: true)
}
}
正如我在手表的设置中看到的那样,HealthKit 已获得适当授权。有任何想法吗?一般对我的代码有什么提示吗?
哇,毕竟这次我发现了问题:行 previousAnchor = newAnchor
需要在 之后 guard
语句。就是这样。