iOS接入HealthKit,获取健康应用步数

Overview

话不多说,先看看官网对HealthKit的解释:

屏幕快照 2018-09-04 15.45.11.png

稍稍翻译一下,创建完成,HealthKit可以完成一下任务:
收集和存储健康和健身数据
分析和可视化数据
实现社交互动

HealthKit中有很多数据,但是没必要全部获取,只需要拿到当前需要的就行。‍♀️

1.启用HealthKit

79f2fd7e-6a9c-4c18-8c70-73ff9b9f992a.png

开启HealthKit之后,在info.plist中增加 Privacy - Health Share Usage DescriptionPrivacy - 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

你可能感兴趣的:(iOS接入HealthKit,获取健康应用步数)