HealthKit接入总结
前言
开发中有需要读写苹果健康app数据的场景,需要使用HealthKit,这里对相关的用法做一个总结分享
1. 准备工作
1.1 判断是否支持使用HealthKit
可以使用下面这个方法
Code: Select all
[HKHealthStore isHealthDataAvailable];1.2 数据的类型
HealthKit中有几种类型的数据,后续对于权限的申请和读写操作都需要明确数据的内心
quantityType身高体重等数据,大部分数据都可读写,部分数据只读categoryType刷牙事件,心率事件等,可读写CharacteristicType性别,血型等数据,只读CorrelationType关联类型,上面的类型都只用一个值就可以写入,一个值表示不了的就需要用到这个关联类型来组织一组值,目前只有两种血压和食物组成
2. 权限获取
在获取权限前需要添加下面的权限获取说明
Code: Select all
<key>Privacy - Health Update Usage Description</key>
<string>health</string>
<key>Privacy - Health Share Usage Description</key>
<string>health</string>2.1 权限申请
Code: Select all
- (void)requestAuthorizationToShareTypes:(nullable NSSet<HKSampleType *> *)typesToShare
readTypes:(nullable NSSet<HKObjectType *> *)typesToRead
completion:(void (^)(BOOL success, NSError * _Nullable error))completion可以通过这种方式来获取权限,中typesToRead是要获取的读权限的数据类型,typesToShare是要获取的写权限的数据类型
2.2 权限查询
Code: Select all
- (HKAuthorizationStatus)authorizationStatusForType:(HKObjectType *)type;
// [self.healthStore authorizationStatusForType:objectType]可以通过该方法查询是否有写入权限,对于读取权限苹果官方做了限制无法查询,没权限时进行读取会读到空数据
2.2 类型构造
Code: Select all
+ (nullable HKQuantityType *)quantityTypeForIdentifier:(HKQuantityTypeIdentifier)identifier;
+ (nullable HKCategoryType *)categoryTypeForIdentifier:(HKCategoryTypeIdentifier)identifier;
+ (nullable HKCharacteristicType *)characteristicTypeForIdentifier:(HKCharacteristicTypeIdentifier)identifier;通过这些方法可以构造出需要的类型,用来获取权限,其中的identifier可以去HKTypeIdentifiers.h文件中查找
3. 数据读取
3.1 quantityType类别读取
读取quantityType类型需要先构造一个HKSampleQuery
Code: Select all
- (instancetype)initWithSampleType:(HKSampleType *)sampleType
predicate:(nullable NSPredicate *)predicate
limit:(NSUInteger)limit
sortDescriptors:(nullable NSArray<NSSortDescriptor *> *)sortDescriptors
resultsHandler:(void(^)(HKSampleQuery *query, NSArray<__kindof HKSample *> * _Nullable results, NSError * _Nullable error))resultsHandler;- 其中
sampleType就传一个HKQuantityType即可(HKQuantityType是sampleType的子类),代表要读取的类型 predicate,查询的时间范围,可以通过下面的方法构造Code: Select all
+ (NSPredicate *)predicateForSamplesWithStartDate:(nullable NSDate *)startDate endDate:(nullable NSDate *)endDate options:(HKQueryOptions)options;limit限制返回数量sortDescriptors数据排序标识resultsHandler完成查询的回调,results包含查询到的数据
构造完成后使用HKHealthStore实例执行即可
Code: Select all
[self.healthStore executeQuery:sampleQuery];3.1.1 数据解析
查询到的resluts中的数据是HKQuantitySample类型,数据就在quantity属性中,要获取到数据可以通过HKQuantity类中的方法
Code: Select all
- (double)doubleValueForUnit:(HKUnit *)unit;其中unit是数据的单位,不通的数据对应不同单位,单位传错会crash,单位也可以在HKTypeIdentifiers.h文件中查看
Code: Select all
// HKUnit 构造
+ (instancetype)unitFromString:(NSString *)string;3.2 categoryType类别读取
categoryType读取和quantityType类型,只在传入要读取的类型时传入一个HKCategoryTyp即可
对于读取到的数据是HKCategorySample类型,不需要单位,直接取里面的value即可
3.2.1 数据解析
对于读取到的数据含义参考不同类型的官方文档,比如HKCategoryTypeIdentifierHandwashingEvent类型,它的值为HKCategoryValueNotApplicable也就是0,代表一次洗手时间,通过获取HKCategorySample中的起始和终止时间来表示这次洗手的时间,同样写入时也只能把value设置为0,用起止时间来表示持续时间
3.3 CharacteristicType类别读取
CharacteristicType类别读取和前两种都不同,对于不同的类型有不同api
Code: Select all
NSError * error;
// HKCharacteristicTypeIdentifierBiologicalSex
HKBiologicalSexObject * res = [self.healthStore biologicalSexWithError:&error];
// HKCharacteristicTypeIdentifierBloodType
HKBloodTypeObject * res = [self.healthStore bloodTypeWithError:&error];
// HKCharacteristicTypeIdentifierDateOfBirth
NSDateComponents * dateComponents = [self.healthStore dateOfBirthComponentsWithError:&error];
// HKCharacteristicTypeIdentifierFitzpatrickSkinType
HKFitzpatrickSkinTypeObject * res = [self.healthStore fitzpatrickSkinTypeWithError:&error];
// HKCharacteristicTypeIdentifierWheelchairUse
HKWheelchairUseObject * res = [self.healthStore wheelchairUseWithError:&error];4. 数据写入
4.1 quantityType类别写入
先用要写入的数据构造一个HKQuantity,单位和读取一样也要传入匹配的
Code: Select all
+ (instancetype)quantityWithUnit:(HKUnit *)unit doubleValue:(double)value;
// [HKQuantity quantityWithUnit:hkUnit doubleValue:value];然后构造一个HKQuantitySample准备写入
Code: Select all
+ (instancetype)quantitySampleWithType:(HKQuantityType *)quantityType
quantity:(HKQuantity *)quantity
startDate:(NSDate *)startDate
endDate:(NSDate *)endDate;
// HKQuantitySample *quantitySample = [HKQuantitySample quantitySampleWithType:quantityType quantity:quantity startDate:startDate endDate:endDate];最后通过healthStore写入,注意写入时要注意线程安全问题
Code: Select all
- (void)saveObject:(HKObject *)object withCompletion:(void (^)(BOOL success, NSError * _Nullable error))completion4.2 categoryType类别写入
直接构造一个HKCategorySample准备进行写入
对于需要写入的value参考不同类型的官方文档,比如HKCategoryTypeIdentifierHandwashingEvent类型,它的值为HKCategoryValueNotApplicable也就是0,写入时只能把value设置为0,用起止时间来表示持续时间
Code: Select all
+ (instancetype)categorySampleWithType:(HKCategoryType *)type
value:(NSInteger)value
startDate:(NSDate *)startDate
endDate:(NSDate *)endDate;
// HKCategorySample *sample = [HKCategorySample categorySampleWithType:Type value:aValue startDate:startDate endDate:endDate];然后通过healthStore写入,注意写入时要注意线程安全问题
Code: Select all
- (void)saveObject:(HKObject *)object withCompletion:(void (^)(BOOL success, NSError * _Nullable error))completion4.3 CorrelationType类别写入
一些特殊数据单独用上面的方法写入不会展示在健康app中,比如血压,虽然收缩压和舒张压都是quantityType,但是单独用上面的方式写入是不行的,因为血压这两个数据是成对出现的
下面以血压为例看看怎么写入
- 首先创建收缩压和舒张压的
HKQuantitySample - 然后将两个数据放到一个
set中Code: Select all
NSMutableSet *objects = [[NSMutableSet alloc] init]; [objects addObject:systolicSample]; [objects addObject:diastolicSample]; - 用包含两个数据的
set创建HKCorrelationCode: Select all
+ (instancetype)correlationWithType:(HKCorrelationType *)correlationType startDate:(NSDate *)startDate endDate:(NSDate *)endDate objects:(NSSet<HKSample *> *)objects; // HKCorrelation *bloodPressure = [HKCorrelation correlationWithType:bloodPressureType startDate:startDate endDate:endDate objects:objects]; - 最后和上面一样通过
healthStore写入