当应用程序处于后台模式时,HealthKit Observer无法正常工作

时间:2015-05-29 20:00:27

标签: ios swift health-kit hksamplequery

我已经跟踪了Apple Docs和stackoverflow上的几个线程,介绍了如何从Health Store中获取数据的后台获取。 到目前为止,我有:

  • HealthKit权利添加到我的appID
  • 添加了必需的背景模式
  • 将代码添加到 AppDelegate.swift ,如Apple建议的那样(下面的代码片段不是关注OOP,只是为了让设施在此处说明

这是我的代码(swift): 如果您的答案是在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在后​​台模式下似乎对我不起作用。

有什么建议吗?

1 个答案:

答案 0 :(得分:1)

根据我的经验,频率&#34; .Immediate&#34;并不好用。查询处理程序插入后台队列。如果频繁添加匹配的样本或iOS正忙,则即时频率不能正常工作。

此外,您无法在HKSampleQuery中使用HKObserverQueryupdateHandler的{​​{1}}可能会有效,但HKObserverQuery的{​​{1}}则不会。观察者查询的处理程序可以在后台模式下执行,但是样本查询之一不能在后台模式下执行。

你应该知道 ONLY resultHandler可以在后台使用