HealthKit之理论知识

简介:


1、#import <HealthKit/HealthKit.h>


2、创建HKHealthStore对象,通过它可以读取和存储用户的health数据。不过在读取和存储之前,首先要通过HKHealthStore执行方法+ (BOOL)isHealthDataAvailable;判断用户设备是否支持HealthKit。


3、我们读取和存储用户的health数据,就必须明确知道要操作的数据类型。在HealthKit里,数据类型有HKObjectType、HKSampleType、HKActivitySummaryType、HKCategoryType、HKCharacteristicType、HKCorrelationType、HKQuantityType和HKWorkoutType。它们的结构关系如图所示。

通过在HKObjectType.h类里定义的方法,

+ (nullable HKQuantityType *)quantityTypeForIdentifier:(NSString *)identifier;

+ (nullable HKCategoryType *)categoryTypeForIdentifier:(NSString *)identifier;

+ (nullable HKCharacteristicType *)characteristicTypeForIdentifier:(NSString *)identifier;

+ (nullable HKCorrelationType *)correlationTypeForIdentifier:(NSString *)identifier;

+ (HKWorkoutType *)workoutType;

+ (HKActivitySummaryType *)activitySummaryType NS_AVAILABLE_IOS(9_3);

可以去创建对应的数据类型。方法参数Identifier,是具体数据Id,在HKTypeIdentitytifiers.h类里定义。它们命名方式都是以所属类型名开始。比如:

    HKObjectType *type1 = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount]; // 步数

    HKObjectType *type2 = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierDistanceWalkingRunning]; // 步行+跑步距离

    HKObjectType *type3 = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierFlightsClimbed];     // 已爬楼层

    HKObjectType *tyep4 = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierActiveEnergyBurned]; // 活动能量

    HKObjectType *type5 = [HKObjectType activitySummaryType];// 健身记录


    HKObjectType *type6 = [HKObjectType correlationTypeForIdentifier:HKCorrelationTypeIdentifierFood];

    

    HKObjectType *type8 = [HKObjectType characteristicTypeForIdentifier:HKCharacteristicTypeIdentifierBiologicalSex]; // 性别

    HKObjectType *type9 = [HKObjectType characteristicTypeForIdentifier:HKCharacteristicTypeIdentifierBloodType];//血型

    HKObjectType *type10 = [HKObjectType characteristicTypeForIdentifier:HKCharacteristicTypeIdentifierDateOfBirth];//出生日期

    HKObjectType *type11 = [HKObjectType characteristicTypeForIdentifier:HKCharacteristicTypeIdentifierFitzpatrickSkinType];//日光反应型皮肤类型

    

    HKObjectType *type12 = [HKObjectType categoryTypeForIdentifier:HKCategoryTypeIdentifierSleepAnalysis];// 睡眠分析

    HKObjectType *type12 = [HKObjectType categoryTypeForIdentifier:HKCategoryTypeIdentifierAppleStandHour]; // 站立小时

    HKObjectType *type12 = [HKObjectType categoryTypeForIdentifier:HKCategoryTypeIdentifierCervicalMucusQuality]; // 宫颈粘液质量

    HKObjectType *type12 = [HKObjectType categoryTypeForIdentifier:HKCategoryTypeIdentifierOvulationTestResult]; // 排卵测试结果

    HKObjectType *type12 = [HKObjectType categoryTypeForIdentifier:HKCategoryTypeIdentifierMenstrualFlow]; // 月经

    HKObjectType *type12 = [HKObjectType categoryTypeForIdentifier:HKCategoryTypeIdentifierIntermenstrualBleeding];// 点滴出血

    HKObjectType *type12 = [HKObjectType categoryTypeForIdentifier:HKCategoryTypeIdentifierSexualActivity]; // 性行为


4、在读取和存储用户的health数据之前,我们需要请求授权,读取和存储哪些类型的Health数据。通过HKHealthStore对象执行- (void)requestAuthorizationToShareTypes:(nullable NSSet<HKSampleType *> *)typesToShare

                               readTypes:(nullable NSSet<HKObjectType *> *)typesToRead

                              completion:(void (^)(BOOL success, NSError * __nullable error))completion;参数shareTypes就是需要授权的存储数据类型,参数readTypes就是需要授权的读取数据类型,completion就是授权完成回调。授权过程是在子线程异步执行。代码参考:

HKObjectType *type1 = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount]; // 步数

    HKObjectType *type2 = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierDistanceWalkingRunning]; // 步行+跑步距离

    HKObjectType *type3 = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierFlightsClimbed];     // 已爬楼层

    HKObjectType *tyep4 = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierActiveEnergyBurned]; // 活动能量

    NSSet *rset = [NSSet setWithObjects:type1, type2, type3, tyep4, nil]; // 读集合

    

    

    HKSampleType *wType1 = [HKSampleType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount];

    HKCategoryType *wType2 = [HKCategoryType categoryTypeForIdentifier:HKCategoryTypeIdentifierSleepAnalysis];

    NSSet *wset = [NSSet setWithObjects:wType1, wType2, nil]; // 写集合

    

    __weak typeof (&*self) weakSelf = self;

    [_healthStore requestAuthorizationToShareTypes:wset readTypes:rset completion:^(BOOL success, NSError * _Nullable error) {

        if (success)

        {

            // 去读取和存储用户的health数据

        } else

        {

            NSLog(@"healthkit不允许读写");

        }

    }];


5、读取用户health数据,HKHealthStore提供了

- (nullable NSDate *)dateOfBirthWithError:(NSError **)error;

- (nullable HKBiologicalSexObject *)biologicalSexWithError:(NSError **)error;

- (nullable HKBloodTypeObject *)bloodTypeWithError:(NSError **)error;

- (nullable HKFitzpatrickSkinTypeObject *)fitzpatrickSkinTypeWithError:(NSError **)error;

可以直接读用户的出生日期、性别、血型和日光反应型皮肤类型。

而需要读取更多的数据,就得创建查询条件去查询数据,查询就得用到HKQuery,它的子类有:

HKSampleQuery(HKSampleType类型数据查询,简称样本查询),HKActivitySummaryQuery(HKActivitySummaryType数据类型查询,即健身记录查询),

HKCorrelationQuery(HKCorrelationType数据类型查询),

HKAnchoredObjectQuery(锚点查询,即分页查询),

HKObserverQuery(观察查询,即查询的数据发生变化时能监听到),

HKStatisticsQuery(统计查询,比如统计今天步数),

HKStatisticsCollectionQuery(从某一时间开始,以一定的时间间隔按条件查询,比如统计今天活动记录中每一小时的步数,即6点多少步,8店多少步,15点多少步),

HKSourceQuery(数据来源查询,比如查询来源小米手环的所有数据)。

代码参考:

// 查询今天步数

NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];

    NSDateComponents *dateCom = [calendar components:NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit fromDate:[NSDate date]];

    

    NSDate *endDate = [calendar dateFromComponents:dateCom];

    

    [dateCom setHour:0];

    [dateCom setMinute:0];

    [dateCom setSecond:0];

    

    NSDate *startDate = [calendar dateFromComponents:dateCom];

    NSPredicate *predicate = [HKQuery predicateForSamplesWithStartDate:startDate endDate:endDate options:HKQueryOptionStrictStartDate];


HKQuantityType *sampleType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount];

    

    //NSSortDescriptors用来告诉healthStore怎么样将结果排序。

    NSSortDescriptor *start = [NSSortDescriptor sortDescriptorWithKey:HKSampleSortIdentifierStartDate ascending:NO];

    NSSortDescriptor *end   = [NSSortDescriptor sortDescriptorWithKey:HKSampleSortIdentifierEndDate ascending:NO];


__weak typeof (&*_healthStore)weakHealthStore = _healthStore;

    

    HKSampleQuery *q1 = [[HKSampleQuery alloc] initWithSampleType:sampleType predicate:predicate limit:HKObjectQueryNoLimit sortDescriptors:@[start,end] resultsHandler:^(HKSampleQuery * _Nonnull query, NSArray<__kindof HKSample *> * _Nullable results, NSError * _Nullable error) {

        double sum = 0;

        double sumTime = 0;

        NSLog(@"步数结果=%@", results);

        for (HKQuantitySample *res in results)

        {

            

            sum += [res.quantity doubleValueForUnit:[HKUnit countUnit]];

            

            NSTimeZone *zone = [NSTimeZone systemTimeZone];

            NSInteger interval = [zone secondsFromGMTForDate:res.endDate];

            

            NSDate *startDate = [res.startDate dateByAddingTimeInterval:interval];

            NSDate *endDate   = [res.endDate dateByAddingTimeInterval:interval];


            sumTime += [endDate timeIntervalSinceDate:startDate];

        }

        int h = sumTime / 3600;

        int m = ((long)sumTime % 3600)/60;

        NSLog(@"运动时长:%@小时%@分", @(h), @(m));

        NSLog(@"运动步数:%@步", @(sum));

        if(error) NSLog(@"1error==%@", error);

        [weakHealthStore stopQuery:query];

        [[NSOperationQueue mainQueue] addOperationWithBlock:^{

                //查询是在多线程中进行的,如果要对UI进行刷新,要回到主线程中

            }];;

    }];

//执行查询

    [_healthStore executeQuery:q1];

查询完成时,有一处还需要我们注意,就是单位转换。单位类HKUnit,哪怎么知道查询得到的数据是什么单位呢,在HKTypeIdentifiers.h类里定义数据Id后面都有标明,

比如:

HK_EXTERN NSString * const HKQuantityTypeIdentifierStepCount NS_AVAILABLE_IOS(8_0);                 // Scalar(Count),               Cumulative

步数的单位是Scalar(Count),我们就到HKUnit.h类搜索Scalar,找到HKUnit扩展@interface HKUnit (Scalar);而(Count)表明需要执行此扩展的+ (instancetype)countUnit; 得到所需的单位类。

当然我也可以为数据类自定义单位类。

通过HKHealthStore对象的方法来做到

- (void)preferredUnitsForQuantityTypes:(NSSet<HKQuantityType *> *)quantityTypes completion:(void(^)(NSDictionary<HKQuantityType*, HKUnit *> *preferredUnits, NSError * __nullable error))completion NS_AVAILABLE_IOS(8_2);


6、存储和删除health数据,通过HKHealthStore对象的方法来做到

存储方法

- (void)saveObject:(HKObject *)object withCompletion:(void(^)(BOOL success, NSError * __nullable error))completion;

- (void)saveObjects:(NSArray<HKObject *> *)objects withCompletion:(void(^)(BOOL success, NSError * __nullable error))completion;


删除方法

- (void)deleteObject:(HKObject *)object withCompletion:(void(^)(BOOL success, NSError * __nullable error))completion;

- (void)deleteObjects:(NSArray<HKObject *> *)objects withCompletion:(void(^)(BOOL success, NSError * __nullable error))completion NS_AVAILABLE_IOS(9_0);

- (void)deleteObjectsOfType:(HKObjectType *)objectType predicate:(NSPredicate *)predicate withCompletion:(void(^)(BOOL success, NSUInteger deletedObjectCount, NSError * __nullable error))completion NS_AVAILABLE_IOS(9_0);


这里主要介绍下参数object,是HKObject数据对象,其包括UUID、来源信息HKSourceHKSourceRevision、设备信息HKDevice和元数据HKMetadata。

HKSource,包括来源名称和唯一标识符,系统8.0以下使用。

HKSourceRevision,包括来源名称、唯一标识符和版本号,系统8.0以上使用。

HKDevice,包括设备的名称、制造商、型号、硬件版本和软件版本等。

HKMetadata,可以设置设备序列号、身体温度传感器的位置、心率传感器的位置、数字签名、是否是室内室外锻炼等。

HKObject有四个子类HKSample、HKWorkout、HKCorrelation和HKCategorySample。


代码参考:

// 睡眠分析

    HKCategoryType *categoryType = [HKCategoryType categoryTypeForIdentifier:HKCategoryTypeIdentifierSleepAnalysis];

    HKDevice *device = [[HKDevice alloc] initWithName:@"文能设备" manufacturer:@"中国制造商" model:@"智能机" hardwareVersion:@"1.0.0" firmwareVersion:@"1.0.0" softwareVersion:@"1.0.0" localIdentifier:@"lizaochengwen" UDIDeviceIdentifier:@"wennengshebei"];

    HKCategorySample *testObject = [HKCategorySample categorySampleWithType:categoryType value:0.25 startDate:[NSDate dateWithTimeIntervalSinceNow:-(24 * 3600)] endDate:[NSDate date] device:device metadata:nil];

    [_healthStore saveObject:testObject withCompletion:^(BOOL success, NSError * _Nullable error) {

        if (success) {

            NSLog(@"文能设备,收集的睡眠记录保存成功");

        } else

        {

             NSLog(@"文能设备,收集的睡眠记录保存失败 %@", error);

        }

    }];

    

    NSMutableArray *list= [[NSMutableArray alloc] init];

    for (float i = 1; i < 100; i++) {

        HKCategorySample *testObject = [HKCategorySample categorySampleWithType:categoryType value:i/100.0 startDate:[NSDate dateWithTimeIntervalSinceNow:-(24 * 3600/i)] endDate:[NSDate date] device:device metadata:nil];

        [list addObject:testObject];

    }

    [_healthStore saveObjects:list withCompletion:^(BOOL success, NSError * _Nullable error) {

        if (success) {

            NSLog(@"文能设备,收集的睡眠记录保存成功");

        } else

        {

            NSLog(@"文能设备,收集的睡眠记录保存失败 %@", error);

        }

    }];

    

    NSSet *dSet= [[NSSet alloc] initWithObjects:@"文能设备", nil];

    NSPredicate *catePredicate = [HKQuery predicateForObjectsWithDeviceProperty:HKDevicePropertyKeyName allowedValues:dSet];

    [_healthStore deleteObjectsOfType:categoryType predicate:catePredicate withCompletion:^(BOOL success, NSUInteger deletedObjectCount, NSError * _Nullable error) {

        if (success) {

            NSLog(@"文能设备,收集的睡眠记录删除成功 %@", @(deletedObjectCount));

        } else

        {

            NSLog(@"文能设备,收集的睡眠记录删除失败 %@", error);

        }

    }];

目录
相关文章
|
6月前
|
存储 JavaScript 前端开发
“纯血鸿蒙”要来了,赶紧入手学习吧
1月18日,华为宣布HarmonyOSNEXT鸿蒙星河版面向开发者开放申请,这一最新版本的鸿蒙系统也被喻为“纯血鸿蒙”。赶紧入手学习吧
355 1
|
6月前
|
算法 数据可视化 vr&ar
【图形学】探秘图形学奥秘:区域填充的解密与实战
【图形学】探秘图形学奥秘:区域填充的解密与实战
53 0
|
2月前
|
缓存 安全
推荐让你事半功倍的5款实用软件
本文推荐了五款高效实用的软件,涵盖音乐管理、家庭娱乐、微信空号检测、笔记管理和系统清理等方面。包括MusicBee、MediaPortal 2、燃精灵、Knowte和BleachBit,每一款都能显著提升工作和学习效率,是不可多得的神器。
53 9
|
3月前
|
C# 机器学习/深度学习 搜索推荐
WPF与机器学习的完美邂逅:手把手教你打造一个具有智能推荐功能的现代桌面应用——从理论到实践的全方位指南,让你的应用瞬间变得高大上且智能无比
【8月更文挑战第31天】本文详细介绍如何在Windows Presentation Foundation(WPF)应用中集成机器学习功能,以开发具备智能化特性的桌面应用。通过使用Microsoft的ML.NET框架,本文演示了从安装NuGet包、准备数据集、训练推荐系统模型到最终将模型集成到WPF应用中的全过程。具体示例代码展示了如何基于用户行为数据训练模型,并实现实时推荐功能。这为WPF开发者提供了宝贵的实践指导。
41 0
|
4月前
|
运维 C# 开发工具
C#实战 | 天行健、上下而求索
【7月更文挑战第7天】使用C语言实现了一个小球(小方块)在屏幕上斜向移动并反弹的程序。当C#入门案例包括创建控制台应用和Windows窗体应用。 1. **控制台应用“天行健,君子以自强不息”** - 使用Visual Studio创建新C#控制台项目,命名为ConsoleAppStrengthenSelf。 - 在Main()方法中使用`Console.WriteLine()`输出励志语句。 - 运行程序,控制台显示结果。 每个项目都涉及Visual Studio的使用,Main()作为程序入口,以及不同类型的用户交互:控制台的文本输出和Windows窗体的图形界面。
46 0
C#实战 | 天行健、上下而求索
|
6月前
|
算法 安全 开发工具
DevChat一网打尽所有大模型——给你全新的编程体验
DevChat一网打尽所有大模型——给你全新的编程体验
77 0
|
机器学习/深度学习 人工智能 自然语言处理
ChatGPT最强专业学习资料集锦
本文旨在整理一份可供参考和学习的专业ChatGPT相关资料,包括ChatGPT相关论文、Github项目、以及当前市场上出现的ChatGPT相关产品等。
ChatGPT最强专业学习资料集锦
|
架构师 算法 测试技术
嵌入式系统软件架构设计(长篇深度好文)
嵌入式系统软件架构设计(长篇深度好文)
4464 0
|
存储 缓存 负载均衡
【小白晋级大师】如何设计一个支持10万人用的ChatGPT对接系统
之前给大家写了ChatGPT对接企业微信的教程,文章结尾说了教程只能适用于小规模使用,现在来写大规模使用的教程
281 1
【小白晋级大师】如何设计一个支持10万人用的ChatGPT对接系统
|
运维 算法 架构师
又爆新作!阿里甩出架构师进阶必备神仙笔记,底层知识全梳理
据有关数据表明,目前Java程序员这个群体的数量不减反增,行业内的竞争也是越来越严重。在同一时间入行的人,经过一段时间的学习后,差距就会显示出来。其实出现这样的原因大多数都是因为学习的方向出了问题。大多数人学Java刚开始只是为了快速就业,但是在工作了之后却没有一个好的学习路线,那些其实很重要的东西只是因为工作上用不到从而忽略掉了,慢慢的才发现自己与别人之间已经存在很大差距了!
下一篇
无影云桌面