Overview
话不多说,先看看官网对HealthKit的解释:
稍稍翻译一下,创建完成,HealthKit可以完成一下任务:
收集和存储健康和健身数据
分析和可视化数据
实现社交互动
HealthKit中有很多数据,但是没必要全部获取,只需要拿到当前需要的就行。♀️
1.启用HealthKit
开启HealthKit之后,在info.plist中增加 Privacy - Health Share Usage Description 与 Privacy - Health Update Usage Description,内容可以随便填写。
2.确保HealthKit可用
import HealthKit
//检测当前HealthKit是否可以使用
if HKHealthStore.isHealthDataAvailable() {
print("HealthKit可以使用")
}
3.创建HKHealthStore
let healthStore = HKHealthStore()
4.请求读取和共享数据的权限
//读取权限
let typestoRead = Set([HKObjectType.workoutType(), //步行+跑步距离
HKObjectType.quantityType(forIdentifier: .stepCount)!, //步数
HKObjectType.quantityType(forIdentifier: .activeEnergyBurned)!, //活动能量
HKObjectType.quantityType(forIdentifier: .distanceCycling)!, // 骑车距离
HKObjectType.quantityType(forIdentifier: .distanceWalkingRunning)!, // 体能训练
HKObjectType.quantityType(forIdentifier: .heartRate)!]) //心率
//写入权限
let typestoShare = Set([
HKObjectType.quantityType(forIdentifier: .stepCount)!,
HKObjectType.quantityType(forIdentifier: .activeEnergyBurned)!,
HKObjectType.quantityType(forIdentifier: .distanceCycling)!, //活动能量
HKObjectType.quantityType(forIdentifier: .distanceWalkingRunning)!,
HKObjectType.quantityType(forIdentifier: .heartRate)!])
healthStore.requestAuthorization(toShare: typestoShare, read: typestoRead, completion: { [weak self] (success, error) in
if !success {
NSLog("Display not allowed")
}else {
self?.readStep()
}
})
5.读取数据
func readStep() {
HKQuantityType.quantityType(forIdentifier: HKQuantityTypeIdentifier.stepCount)
//NSSortDescriptors用来告诉healthStore怎么样将结果排序
let start = NSSortDescriptor(key: HKSampleSortIdentifierStartDate, ascending: false)
let stop = NSSortDescriptor(key: HKSampleSortIdentifierEndDate, ascending: false)
let now = Date()
guard let sampleType = HKSampleType.quantityType(forIdentifier: HKQuantityTypeIdentifier.stepCount) else {
fatalError("*** This method should never fail ***")
}
let calendar = Calendar(identifier: Calendar.Identifier.gregorian)
var dataCom = calendar.dateComponents([.year, .month, .day, .hour, .minute, .second], from: now)
let endDate = calendar.date(from: dataCom) //设置查询的截止时间(当前)
dataCom.hour = 0
dataCom.minute = 0
dataCom.second = 0
let startDate = calendar.date(from: dataCom) //设置查询的起始时间(当天0点)
let predicate = HKQuery.predicateForSamples(withStart: startDate, end: endDate, options: HKQueryOptions.strictStartDate)
var localSum: Double = 0 //手机写入步数
var currentDeviceSum: Double = 0 //软件写入步数
let query = HKSampleQuery(sampleType: sampleType, predicate: predicate, limit: Int(HKObjectQueryNoLimit), sortDescriptors: [start, stop]) { (query, results, error) in
guard (results as? [HKQuantitySample]) != nil else {
// fatalError("An error occured fetching the user's tracked food. In your app, try to handle this error gracefully. The error was: \(String(describing: error?.localizedDescription))");
print("获取步数error ---> \(String(describing: error?.localizedDescription))")
return
}
for res in results! {
// res.sourceRevision.source.bundleIdentifier 当前数据来源的BundleId
// Bundle.main.bundleIdentifier 当前软件的BundleId
if res.sourceRevision.source.bundleIdentifier == Bundle.main.bundleIdentifier {
print("app写入数据")
let _res = res as? HKQuantitySample
currentDeviceSum = currentDeviceSum + (_res?.quantity.doubleValue(for: HKUnit.count()))!
}else { //手机录入数据
let _res = res as? HKQuantitySample
localSum = localSum + (_res?.quantity.doubleValue(for: HKUnit.count()))!
}
}
print("当前步数 -- \(currentDeviceSum)")
print("当前步数 -- \(localSum)")
// DispatchQueue.main.async { [weak self] in
//
// }
}
healthStore.execute(query) //开始查询
}
6.存入数据
healthStore.requestAuthorization(toShare: typestoShare, read: typestoRead, completion: { [weak self] (success, error) in
if !success {
NSLog("Display not allowed")
}else {
//写入的时间点
let now = Date()
let startDate = Date(timeInterval: -10, since: now)
let countUnit = HKUnit.count()
// 写入的步数
let countUnitQuantity = HKQuantity.init(unit: countUnit, doubleValue: 1000)
let countUnitType = HKQuantityType.quantityType(forIdentifier: HKQuantityTypeIdentifier.stepCount)
let stepCountSample = HKQuantitySample.init(type: countUnitType!, quantity: countUnitQuantity, start: startDate, end: now)
self?.healthStore.save(stepCountSample) { (isSuccess, error) in
if isSuccess {
print("保存成功 ----> \(isSuccess)")
}else {
print("error -----> \(String(describing: error))")
}
}
self?.readStep()
}
})
*所有健康数据类型(HKObjectType)
HealthKit使用子类来识别HealthKit中存储的不同类型的数据:HKObjectType
* HKCharacteristicType 表示通常不随时间变化的数据(例如,血型)。
* HKQuantityType 表示包含数值的样本(例如消耗的卡路里)。
* HKCategoryType 表示包含可能值的短列表中的选项的样本(例如睡眠分析)。
* HKCorrelationType 表示包含许多数量或类别样本的复杂样本(例如,包含许多营养样本的食物样本)。
* HKWorkoutType表示锻炼及其相关数据(有关更多信息,请参阅锻炼)。
let bloodType = HKObjectType.characteristicType(forIdentifier: .bloodType)
let caloriesConsumed = HKObjectType.quantityType(forIdentifier: .dietaryEnergyConsumed)
let sleepAnalysis = HKObjectType.categoryType(forIdentifier: .sleepAnalysis)
let food = HKObjectType.correlationType(forIdentifier: .food)
以上是类型,具体可以获取到哪些数据请参考https://developer.apple.com/documentation/healthkit/hkobjecttype
End
当使用了HealthKit的项目提交时,需要注意在 iTunes Connection项目描述中加入项目使用了健康应用数据的提示
demo https://github.com/duke3312/healthKitDemo