【发布时间】:2015-05-29 20:00:26
【问题描述】:
我已关注Apple Docs 和 stackoverflow 上的几个线程,了解如何实现从 Health Store 后台获取数据。 到目前为止,我有:
- 在我的 appID 中添加了 HealthKit 授权
- 添加了必需的后台模式
- 按照 Apple 的建议将代码添加到 AppDelegate.swift(下面的 sn-p 不遵循 OOP 只是为了方便在此处进行说明)
这是我的代码(快速): 如果您的答案是 Obj-C 并且有效,请同时说明,我将不得不翻译它,但这没问题。
AppDelegate.swift
var healthStore: HKHealthStore?
var bpmSamples: [HKQuantitySample]?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
let dataTypesToWrite = [ ]
let dataTypesToRead = [
HKQuantityType.quantityTypeForIdentifier(HKQuantityTypeIdentifierHeartRate),
HKQuantityType.quantityTypeForIdentifier(HKQuantityTypeIdentifierBodyMassIndex),
HKCharacteristicType.characteristicTypeForIdentifier(HKCharacteristicTypeIdentifierDateOfBirth)
]
if self.healthStore == nil {
self.healthStore = HKHealthStore()
}
self.healthStore?.requestAuthorizationToShareTypes(NSSet(array: dataTypesToWrite as [AnyObject]) as Set<NSObject>,
readTypes: NSSet(array: dataTypesToRead) as Set<NSObject>, completion: {
(success, error) in
if success {
self.addQueryObserver()
println("User completed authorisation request.")
} else {
println("The user cancelled the authorisation request. \(error)")
}
})
return true
}
func addQueryObserver(){
let sampleType =
HKObjectType.quantityTypeForIdentifier(HKQuantityTypeIdentifierHeartRate)
let query = HKObserverQuery(sampleType: sampleType, predicate: nil) {
query, completionHandler, error in
if error != nil {
// Perform Proper Error Handling Here...
println("*** An error occured while setting up the stepCount observer. \(error.localizedDescription) ***")
abort()
}
println("query is running")
self.performQueryForHeartBeatSamples()
completionHandler()
}
healthStore?.executeQuery(query)
healthStore?.enableBackgroundDeliveryForType(sampleType, frequency:.Immediate, withCompletion:{
(success:Bool, error:NSError!) -> Void in
let authorized = self.healthStore!.authorizationStatusForType(sampleType)
println("HEALTH callback success", success)
println("HEALTH callback authorized", sampleType)
})
if HKHealthStore.isHealthDataAvailable() == false {
println("HEALTH data not available")
return
} else {
println("HEALTH OK")
self.performQueryForHeartBeatSamples()
}
}
// MARK: - HealthStore utility methods
func performQueryForHeartBeatSamples() {
let endDate = NSDate()
let startDate = NSCalendar.currentCalendar().dateByAddingUnit(.CalendarUnitMonth, value: -2, toDate: endDate, options: nil)
var heartRate : HKQuantityType = HKQuantityType.quantityTypeForIdentifier(HKQuantityTypeIdentifierHeartRate)
let predicate = HKQuery.predicateForSamplesWithStartDate(startDate, endDate: endDate, options: .None)
let query = HKSampleQuery(sampleType: heartRate, predicate: predicate, limit: 0, sortDescriptors: nil, resultsHandler: {
(query, results, error) in
if results == nil {
println("There was an error running the query: \(error)")
}
dispatch_async(dispatch_get_main_queue()) {
self.bpmSamples = results as? [HKQuantitySample]
let heartRateUnit: HKUnit = HKUnit.countUnit().unitDividedByUnit(HKUnit.minuteUnit())
if self.bpmSamples?.count > 0 {
if let sample = self.bpmSamples?[self.bpmSamples!.count - 1] {
println(sample.quantity!.description)
let quantity = sample.quantity
var value = quantity.doubleValueForUnit(heartRateUnit)
println("bpm: \(value)")
}
}
else {
println("No Data")
}
}
})
self.healthStore?.executeQuery(query)
}
所以,问题是我只有在我手动将应用程序从后台恢复到活动状态时才会收到更新。HKObserverQuery 在后台模式下似乎对我不起作用。
有什么建议吗?
【问题讨论】:
-
您是否在设备上进行调试,并且是否从“调试”菜单手动模拟了后台提取?
-
我在真实设备和模拟器设备上都对其进行了测试,在这两种情况下,我都将新数据手动添加到 HealthKit 中,并等待
HKObserverQuery发挥作用。我刚刚测试了后台获取,但它什么也没做。 -
模拟器不行,要在真机上模拟后台抓取,你试过吗?
-
问题似乎是当我进入健康应用程序或我的应用程序时,它会强制健康应用程序刷新数据。虽然我的应用程序处于打开状态,但 Health 应用程序仅在它认为正确时才加载数据(而不是在我要求 HealthKit 这样做时)..所以..我对数据的请求很遗憾地不同步,直到 Health 应用程序决定刷新或者从 Apple Watch 上的传感器获取数据后,可能需要很长时间才能从 Watch 获取数据。无论哪种方式,从开发人员的角度来看,这都不是应有的方式。我很快就会在 Watch OS 2 上进行测试。
-
你找到解决办法了吗@HugoAlonso?
标签: ios swift healthkit hksamplequery