Мне нужно наблюдать данные о частоте сердечных сокращений в 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)
}
}
}