HealthKit Observer не работает, когда приложение находится в фоновом режиме

Я следил за Apple Docs и несколькими потоками в stackru, чтобы узнать, как добиться фоновой выборки данных из Health Store. Пока что у меня есть:

  • Добавил право HealthKit в мой appID
  • Добавлены необходимые режимы фона
  • Добавлен код в AppDelegate.swift, как предлагает Apple (фрагмент ниже не следует за ООП только для того, чтобы можно было так заявить здесь)

Это мой код (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 ответ

По моему опыту, частота ". Немедленно" не работает хорошо. Обработчик запросов вставляется в фоновую очередь. Если подходящие сэмплы часто добавляются или iOS занята, мгновенная частота не работает должным образом.

Кроме того, вы не можете использовать HKSampleQuery в HKObserverQuery, updateHandler из HKObserverQuery может работать, но resultHandler из HKSampleQuery не буду. Обработчик запроса наблюдателя может быть выполнен в фоновом режиме, но образец запроса не может быть выполнен в фоновом режиме.

Вы должны знать, что ТОЛЬКО HKObserverQuery можно использовать в фоновом режиме

Другие вопросы по тегам