iOS HealthKit 介绍

一、简介

HealthKit是一款用于搜集和办理医疗和健康相关数据的开发工具包,它为开发者供给了拜访用户健康数据的API和框架,并使得这些数据能够与iOS设备上的其他应用程序相互共享。

HealthKit允许应用程序搜集和办理各种类型的健康数据,包含身体丈量数据(如体重、身高和心率)、健身数据(如步数和距离)、饮食数据、睡觉数据和心理健康数据等。这些数据能够从多个来历搜集,如从硬件设备(如智能手表、智能手机和健身跟踪器)中获取,或由用户手动输入。

二、权限配置

1. 在开发者账号中勾选HealthKit

在这里插入图片描述

2. 在targets的capabilities中添加HealthKit。

在这里插入图片描述

3. infoPlist需要配置权限

Privacy - Health Share Usage Description
需要您的同意,才能访问健康更新,给您带来更好的服务
Privacy - Health Update Usage Description
需要您的同意,才能分享健康数据,给您带来更好的服务
在这里插入图片描述

注意:iOS13 这里描述太粗糙,会导致程序崩溃。

三、创建健康数据管理类

1. 引入头文件

import HealthKit

2. 健康数据读写权限

// 写权限
    private func dataTypesToWrite() -> Set<HKSampleType> {
        // 步数
        let stepCountType = HKObjectType.quantityType(forIdentifier: .stepCount)
        // 身高
        let heightType = HKObjectType.quantityType(forIdentifier: .height)
        // 体重
        let weightType = HKObjectType.quantityType(forIdentifier: .bodyMass)
        // 活动能量
        let activeEnergyType = HKObjectType.quantityType(forIdentifier: .activeEnergyBurned)
        // 体温
        let temperatureType = HKObjectType.quantityType(forIdentifier: .bodyTemperature)
        // 睡眠分析
        let sleepAnalysisType = HKObjectType.categoryType(forIdentifier: .sleepAnalysis)
        
        let setTypes = Set([stepCountType, heightType, weightType, activeEnergyType, temperatureType, sleepAnalysisType].compactMap { $0 })
        return setTypes
    }
    
    // 读权限
    private func dataTypesToRead() -> Set<HKObjectType> {
        // 步数
        let stepCountType = HKObjectType.quantityType(forIdentifier: .stepCount)
        // 身高
        let heightType = HKObjectType.quantityType(forIdentifier: .height)
        // 体重
        let weightType = HKObjectType.quantityType(forIdentifier: .bodyMass)
        // 体温
        let temperatureType = HKObjectType.quantityType(forIdentifier: .bodyTemperature)
        // 出生日期
        let birthdayType = HKObjectType.characteristicType(forIdentifier: .dateOfBirth)
        // 性别
        let sexType = HKObjectType.characteristicType(forIdentifier: .biologicalSex)
        // 步数+跑步距离
        let distance = HKObjectType.quantityType(forIdentifier: .distanceWalkingRunning)
        // 活动能量
        let activeEnergyType = HKObjectType.quantityType(forIdentifier: .activeEnergyBurned)
        // 睡眠分析
        let sleepAnalysisType = HKObjectType.categoryType(forIdentifier: .sleepAnalysis)
        
        let setTypes = Set([stepCountType, heightType, weightType, activeEnergyType, birthdayType, sexType, distance, temperatureType, sleepAnalysisType].compactMap { $0 })
        return setTypes
    }

3. 检查权限

/// 检查是否支持获取健康数据
    public func authorizeHealthKit(_ compltion: ((_ success: Bool, _ error: Error?) -> Void)?) {
        guard HKHealthStore.isHealthDataAvailable() == true else {
            let error = NSError(domain: "不支持健康数据", code: 2, userInfo: [NSLocalizedDescriptionKey: "HealthKit is not available in th is Device"])
            if let compltion = compltion {
                compltion(false, error)
            }
            return
        }
        let writeDataTypes = dataTypesToWrite()
        let readDataTypes = dataTypesToRead()
        healthStore.requestAuthorization(toShare: writeDataTypes, read: readDataTypes) { success, error in
            if let compltion = compltion {
                compltion(success, error)
            }
        }
    }

4. 读取步数数据

/// 获取步数
    public func getStepCount(_ completion: @escaping ((_ stepValue: String?, _ error: Error?) -> Void)) {
        // 要检索的数据类型。
        guard let stepType = HKObjectType.quantityType(forIdentifier: .stepCount) else {
            let error = NSError(domain: "不支持健康数据", code: 2, userInfo: [NSLocalizedDescriptionKey: "HealthKit is not available in th is Device"])
            completion(nil, error)
            return
        }
        
        // NSSortDescriptors用来告诉healthStore怎么样将结果排序。
        let start = NSSortDescriptor.init(key: HKSampleSortIdentifierStartDate, ascending: false)
        let end = NSSortDescriptor.init(key: HKSampleSortIdentifierEndDate, ascending: false)
        /*
         @param         sampleType      要检索的数据类型。
         @param         predicate       数据应该匹配的基准。
         @param         limit           返回的最大数据条数
         @param         sortDescriptors 数据的排序描述
         @param         resultsHandler  结束后返回结果
         */
        let query = HKSampleQuery.init(sampleType: stepType, predicate: HealthKitManager.getStepPredicateForSample(), limit: HKObjectQueryNoLimit, sortDescriptors: [start, end]) { _, results, error in
            guard let results = results else {
                completion(nil, error)
                return
            }
            print("resultCount = (results.count) result = (results)")
            // 把结果装换成字符串类型
            var totleSteps = 0
            results.forEach({ quantitySample in
                guard let quantitySample = quantitySample as? HKQuantitySample else {
                    return
                }
                let quantity = quantitySample.quantity
                let heightUnit = HKUnit.count()
                let usersHeight = quantity.doubleValue(for: heightUnit)
                totleSteps += Int(usersHeight)
            })
            print("最新步数:(totleSteps)")
            completion("(totleSteps)", error)
        }
        healthStore.execute(query)
    }

5. 写入健康数据

/// 写入数据
    public func writeStep() {
        let steps = HKObjectType.quantityType(forIdentifier: .stepCount)!
        let quantity = HKQuantity(unit: HKUnit.count(), doubleValue: 1000)
        let now = Date()
        let start = now.addingTimeInterval(-3600 * 24)
        let end = now
        let sample = HKQuantitySample(type: steps, quantity: quantity, start: start, end: end)
        let healthStore = HKHealthStore()
        healthStore.save(sample) { (success, _) in
            if success {
                // 数据已写入 HealthKit
            } else {
                // 写入数据失败
            }
        }
    }

四、运行获取权限页面

在这里插入图片描述