使用HealthKit的后台传送检索步骤后,在后台将数据写入Firebase [英] Write data to Firebase in the background after retrieving steps with HealthKit's background delivery

查看:64
本文介绍了使用HealthKit的后台传送检索步骤后,在后台将数据写入Firebase的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个HKObserverQuery设置来在后台获取步骤(在application:didFinishLaunchingWithOptions:中调用了enableBackgroundDelivery方法).

I have an HKObserverQuery setup to fetch steps in the background (enableBackgroundDelivery method is called in application:didFinishLaunchingWithOptions:).

这些步骤是在后台检索的,但是我也想将检索到的步骤存储在Firebase数据库中.但是,此部分失败了,Firebase中没有存储任何内容.当应用程序位于前台时,用于存储步骤的方法可以正常工作.在后台如何在Firebase中成功写入数据的任何想法将不胜感激.

The steps are retrieved in the background, but I would also like to store the retrieved steps in a Firebase database. This part is failing though, nothing is stored in Firebase. The method to store the steps does work correctly when the app is in the foreground. Any ideas on how to successfully write data in Firebase while in the background would be appreciated.

class HealthKitManager {

    static let shared = HealthKitManager()
    private let healthStore = HKHealthStore()
    private let stepsQuantityType = HKQuantityType.quantityType(forIdentifier: .stepCount)!

    private init() {

    }

    func getTodaysStepCount(completion: @escaping (Double) -> Void) {
        let now = Date()
        let startOfDay = Calendar.current.startOfDay(for: now)
        let predicate = HKQuery.predicateForSamples(withStart: startOfDay, end: now, options: .strictStartDate)

        let query = HKStatisticsQuery(quantityType: stepsQuantityType, quantitySamplePredicate: predicate, options: .cumulativeSum) { (_, result, error) in
            var resultCount = 0.0

            guard let result = result else {
                log.error("Failed to fetch steps = \(error?.localizedDescription ?? "N/A")")
                completion(resultCount)
                return
            }

            if let sum = result.sumQuantity() {
                resultCount = sum.doubleValue(for: HKUnit.count())
            }

            DispatchQueue.main.async {
                completion(resultCount)
            }
        }

        healthStore.execute(query)
    }

    func enableBackgroundDelivery() {
        let query = HKObserverQuery(sampleType: stepsQuantityType, predicate: nil) { [weak self] (query, completionHandler, error) in
            if let error = error {
                log.error("Observer query failed = \(error.localizedDescription)")
                return
            }

            self?.getTodaysStepCount(completion: { steps in
                // Store steps using Firebase:
                StepsManager.shared.updateUserSteps(steps)
                completionHandler()
            })
        }

        healthStore.execute(query)
        healthStore.enableBackgroundDelivery(for: stepsQuantityType, frequency: .hourly) { (success, error) in
            log.debug("Background delivery of steps. Success = \(success)")

            if let error = error {
                log.error("Background delivery of steps failed = \(error.localizedDescription)")
            }
        }
    }

}

推荐答案

好,我解决了这个问题.问题在于,我实际上是在完成向Firebase的保存之前,调用了completeHandler,告诉HealthKit我已经完成了自己的操作.保存到Firebase是异步完成的.

Ok, I solved this. The problem was that I was calling the completionHandler, telling HealthKit that I was done with my operation, before the saving to Firebase was actually completed. Saving to Firebase is done asynchronously.

我在StepsManager.shared.updateUserSteps函数中添加了完成处理程序:

I added a completion handler to StepsManager.shared.updateUserSteps function:

func updateUserSteps(_ steps: Double, completion: (() -> Void)? = nil) {
    let stepsReference = databaseInstance.reference(withPath: stepsPath)
    stepsReference.setValue(steps) { _, _ in
        completion?()
    }
}

,当databaseRef.setValue完成时触发.然后,我将观察者查询更新为以下内容:

which is triggered when the databaseRef.setValue has completed. I then updated the observer query to the following:

self?.getTodaysStepCount(completion: { steps in
    StepsManager.shared.updateUserSteps(steps) {
        completionHandler() // the HKObserverQueryCompletionHandler
    }
})

Firebase操作现在可以正确完成.

The Firebase operation completes correctly now.

这篇关于使用HealthKit的后台传送检索步骤后,在后台将数据写入Firebase的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆