首页 > 解决方案 > 当应用程序处于后台时,Healthkit 查询不起作用

问题描述

我需要观察 Healthkit 中的心率数据,然后相应地向用户发送通知。代码运行良好,但每次我必须将应用程序带到前台才能获得通知。我需要它持续工作。查询似乎无法在后台运行。

我已经在网上检查了几乎所有内容,但找不到满足我需要的解决方案。任何帮助,将不胜感激!

编辑:还实现了后台模式。我检查了后台获取。还是不行...

我在下面添加了我的代码片段:

func requestHealthKitPermission(successCallback: @escaping () -> Void) {
    let sampleType: Set<HKSampleType> = [HealthKitService.heartRateType]
    let healthKitStore = HKHealthStore()

    healthKitStore.requestAuthorization(toShare: sampleType, read: sampleType) { (success, error) in

        if success {
            successCallback()
            self.startObservingNewHeartRates()

        }

        if let error = error {
            print("Error requesting health kit authorization: \(error)")
        }
    }
}

func startObservingNewHeartRates() {
    // open observer query

    let query = HKObserverQuery(sampleType: HealthKitService.heartRateType,
                                predicate: nil) { (query, completionHandler, error) in
                                    DispatchQueue.main.async {
                                        self.updateHeartRates(completionHandler: completionHandler)

                                    }
    }
    healthKitStore.execute(query)
    //  Enable background delivery
    healthKitStore.enableBackgroundDelivery(for: HealthKitService.heartRateType, frequency: .immediate) { (success, error) in
        if let error = error {
            print("could not enable background delivery: \(error)")
        }
        if success {
            print("background delivery enabled")
        }
    }

}
func updateHeartRates(completionHandler: @escaping () -> Void) {

    var anchor: HKQueryAnchor?

    if let data = UserDefaults.standard.object(forKey: Constants.UserDefaults.HEART_RATE_ANCHOR_KEY) as? Data {
        anchor = try? NSKeyedUnarchiver.unarchivedObject(ofClass: HKQueryAnchor.self, from: data)
    }

    let sampleType =  HKQuantityType.quantityType(forIdentifier: HKQuantityTypeIdentifier.heartRate)!
    let anchoredQuery = HKAnchoredObjectQuery(type: sampleType, predicate: nil, anchor: anchor, limit: HKObjectQueryNoLimit) {  query, newSamples, deletedSamples, newAnchor, error in

        self.handleNewHeartRates(new: newSamples!, deleted: deletedSamples!)

        if let newAnchor = newAnchor {
            let data = try? NSKeyedArchiver.archivedData(withRootObject: newAnchor, requiringSecureCoding: false)
            UserDefaults.standard.set(data, forKey: Constants.UserDefaults.HEART_RATE_ANCHOR_KEY)
            print("Wrote new Anchor")
        }

        completionHandler()
    }
    healthKitStore.execute(anchoredQuery)
}

func handleNewHeartRates(new: [HKSample], deleted: [HKDeletedObject]) {

    let dateFormatter = DateFormatter()
    dateFormatter.dateStyle = .short
    dateFormatter.timeStyle = .full

    let mapped = new.map { (sample) -> String? in
        guard let hrSample: HKQuantitySample = sample as? HKQuantitySample else { return nil }

        let heartRate = hrSample.quantity.doubleValue(for: HealthKitService.heartRateUnit)

        if heartRate >= 70 { // TODO: extract to Constants
            DispatchQueue.main.async {
                self.viewController?.setupHeartRateNotifications()

            }
        }
        return "\(heartRate)bpm @ \(dateFormatter.string(from: hrSample.startDate)) "
    }.compactMap { $0 }

    print(" ❤❤❤❤❤ new heartRate")
    mapped.forEach { (line) in
        print(line)
    }

    if let latestRecording = new.last {
        let formattedDate = dateFormatter.string(from: latestRecording.endDate)
        UserDefaults.standard.set(formattedDate, forKey: Constants.UserDefaults.LATEST_HEART_RATE_RECORDING_DATE_KEY)
    }
}

}

标签: swiftbackground-processhealthkitobjectqueryhkobserverquery

解决方案


尝试添加后台模式功能,并添加复选框后台处理和后台获取。希望它有效。


推荐阅读