关于HealthKit的enableBackgroundDelivery方法更新通知接收位置的问询
关于HealthKit后台推送接收位置的清晰解答
嘿,我来帮你把这个问题理清楚~首先得明确两个核心点:enableBackgroundDelivery的完成处理程序的作用,以及真正接收数据更新通知的地方。
先搞懂:enableBackgroundDelivery的完成处理程序是干嘛的?
这个完成handler绝对不是用来接收HealthKit数据更新通知的!它的唯一职责是告诉你:你申请的后台推送权限是否成功了。比如,如果用户拒绝了HealthKit权限,或者系统出现了错误,这个handler会返回对应的错误信息;如果成功,就会返回nil。你只需要在这里处理权限请求的结果,完全不用放数据更新的逻辑。
真正接收数据更新的地方
当Health app里有数据更新时,系统会给你的应用发送一个静默推送,你需要在以下两个场景对应的方法里处理:
1. App Delegate(iOS 12及以下,或未使用Scene架构的项目)
在AppDelegate里实现application(_:didReceiveRemoteNotification:fetchCompletionHandler:)方法,这个方法会在应用处于后台/挂起状态时被触发:
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) { // 先确认HealthKit服务可用 guard HKHealthStore.isHealthDataAvailable() else { completionHandler(.failed) return } let healthStore = HKHealthStore() // 替换成你实际关注的健康数据类型,比如步数 let targetDataType = HKObjectType.quantityType(forIdentifier: .stepCount)! // 用HKObserverQuery监听数据变化(这是Apple推荐的方式) let observerQuery = HKObserverQuery(sampleType: targetDataType, predicate: nil) { [weak self] query, observerCompletion, error in guard let self = self else { return } if let error = error { print("HealthKit查询出错:\(error.localizedDescription)") observerCompletion() completionHandler(.failed) return } // 这里执行具体的数据查询,比如获取最新的步数记录 self.fetchLatestHealthData(from: healthStore) { success in observerCompletion() completionHandler(success ? .newData : .noData) } } healthStore.execute(observerQuery) } // 示例:获取最新步数的辅助方法 private func fetchLatestHealthData(from healthStore: HKHealthStore, completion: @escaping (Bool) -> Void) { let stepType = HKObjectType.quantityType(forIdentifier: .stepCount)! let sortByLatest = NSSortDescriptor(key: HKSampleSortIdentifierStartDate, ascending: false) let query = HKSampleQuery(sampleType: stepType, predicate: nil, limit: 1, sortDescriptors: [sortByLatest]) { _, samples, error in if let error = error { print("获取健康数据失败:\(error.localizedDescription)") completion(false) return } if let latestSample = samples?.first as? HKQuantitySample { let stepCount = latestSample.quantity.doubleValue(for: HKUnit.count()) print("最新步数:\(stepCount)") // 这里可以处理数据,比如本地存储、上传服务器等 completion(true) } else { completion(false) } } healthStore.execute(query) }
2. Scene Delegate(iOS 13+,使用Scene架构的项目)
如果你的项目采用了Scene架构,那就要在SceneDelegate里实现scene(_:didReceiveRemoteNotification:fetchCompletionHandler:)方法,逻辑和上面完全一致,只是方法所在的类不同而已。
一句话总结
- ✅ 接收HealthKit数据更新通知:在App Delegate/Scene Delegate的远程推送处理方法里
- ❌ 不要在
enableBackgroundDelivery的完成handler里处理数据更新,它只负责确认权限请求结果
内容的提问来源于stack exchange,提问作者iBug
相关产品推荐
相关产品推荐

