Demo 展示效果
前言
隨著人們對健康的重視,移動端兩大巨頭Apple和Google都推出了各自的健康庫 Apple Health , Google Fit ,它們集成大部分健康中所用到的數(shù)據(jù)類型,各個應用根據(jù)自己所擅長的領域寫入相關健康健身數(shù)據(jù),或共享其庫中其他健康數(shù)據(jù),以達各盡所長,數(shù)據(jù)共享!
簡述
HealthKit框架提供了一個結構,應用可以使用它來分享健康和健身數(shù)據(jù)。HealthKit管理從不同來源獲得的數(shù)據(jù),并根據(jù)用戶的偏好設置,自動將不同來源的所有數(shù)據(jù)合并起來。應用還可以獲取每個來源的原始數(shù)據(jù),然后執(zhí)行自己的數(shù)據(jù)合并。
HealthKit另外提供了一個應用來幫助管理用戶的健康數(shù)據(jù)。健康應用為用戶展示HealthKit的數(shù)據(jù)。用戶可以使用健康應用來查看、添加、刪除或者管理其全部的健康和健身數(shù)據(jù)。用戶還可以編輯每種數(shù)據(jù)類型的分享權限。
HealthKit和健康應用在iPad上都不可用。
隱私
由于健康數(shù)據(jù)可能是敏感的,HealthKit通過精確控制哪些信息允許應用讀取,從而讓用戶可以控制這些數(shù)據(jù)。用戶必須明確設置每個應用在HealthKit存儲中讀寫的權限。用戶可以單獨為每種數(shù)據(jù)類型設置準許或拒絕的權限。例如,用戶可以允許你的應用讀取計步數(shù)據(jù),但是不允許讀取用戶心率數(shù)據(jù)。為了防止可能的信息泄露,應用在不調(diào)用相關訪問接口時,是不知道它是否被禁止讀取數(shù)據(jù)的。
HealthKit的數(shù)據(jù)不會保存在iCloud中,也不會在多設備間同步。這些數(shù)據(jù)只會保存在用戶的本地設備中。為了安全考慮,當設備沒有解鎖時,HealthKit存儲的數(shù)據(jù)是加密的。
另外,你的應用如果主要不是提供健康或健身服務的話,那就不能調(diào)用HealthKit的API。如果你的應用提供健康和健身服務,就必須要在App Store相關應用簡介和應用界面上明確的表明。
使用HealthKit特別注意
你的應用不應該將HealthKit收集的數(shù)據(jù)用于廣告或類似的服務。注意,在使用HealthKit框架應用中可以插播廣告,但是你不能使用HealthKit中的數(shù)據(jù)來服務廣告。
在沒有用戶的明確允許下,你不能向第三方展示任何HealthKit收集的數(shù)據(jù)。即使用戶允許,你也只能向提供健康或健身服務的第三方展示這些數(shù)據(jù)。
你不能將HealthKit收集的數(shù)據(jù)出售給廣告平臺、數(shù)據(jù)代理人或者信息經(jīng)銷商。
如果用戶允許,你可以將HealthKit數(shù)據(jù)共享給第三方用于醫(yī)學研究。注意是用戶允許
你必須明確說明,你和你的應用會怎樣使用用戶的HealthKit數(shù)據(jù)。
應用中使用了HealthKit 上 App Store 特別注意
-
一定要添加隱私政策網(wǎng)址鏈接,并注明健康數(shù)據(jù)使用的隱私相關條例。例如:
- 在App里您設置身高、體重時,根據(jù)您之前是否允許授權權限,XXX將依據(jù)您給的權限是否把信息寫入蘋果健康應用。
- 在App里同步計步、睡眠、心率數(shù)據(jù)時,根據(jù)您之前是否允許授權權限,XXX將依據(jù)您給的權限是否把信息寫入蘋果健康應用。
-
應用介紹中一定要注明:此版本支持你使用Apple健康應用程序
- 審核詳情請參考 App Store Review Guidelines中的HealthKit章節(jié)。
HealthKit設計目標
HealthKit是用來在應用間以一種有意義的方式共享數(shù)據(jù)。為了達到這點,框架限制只能使用預先定義好的數(shù)據(jù)類型和單位。這些限制保證了其他應用能理解這些數(shù)據(jù)是什么意思,以及怎樣使用。因此,開發(fā)者不能創(chuàng)建自定義數(shù)據(jù)類型和單位。而HealthKit盡量會提供一個完整的數(shù)據(jù)類型和單位。
HealthKit 存儲理念
框架大量使用了子類化,在相似的類間創(chuàng)建層級關系。通常這些類間都有一些細微但是重要的差別。還有不少和它相關的類,需要正確搭配,才能一起工作。存儲在HealthKit中的數(shù)據(jù)都是由對象和對象所屬類型組成,這個概念一定要刻入腦海,你才能理解整個存儲結構。所有對象都是基于HKObject,所有對象所屬的類型都是基于HKObjectType。下面簡單介紹下這兩個類:
-
HKObject我們不能直接使用,而是使用它的子類。子類有:
-
HKObject 主要分為兩類:特征和樣本。特征對象代表一些基本不變的數(shù)據(jù)。例如:用戶的生日、血型和生理性別,膚色。你的應用不能寫入特征數(shù)據(jù)。用戶必須通過健康應用來輸入或者修改這些數(shù)據(jù)。
- 樣本對象是某個特定時間斷的數(shù)據(jù)。所有的樣本對象都是HKSample的子類。它們都有下列屬性:
-
sampleType
: 樣本類型。例如:一個睡眠分析樣本、一個身高樣本或者一個計步樣本。 -
startDate
: 樣本的開始時間。 -
endDate
: 樣本的結束時間。
-
- 樣本對象是某個特定時間斷的數(shù)據(jù)。所有的樣本對象都是HKSample的子類。它們都有下列屬性:
-
HKObject 所有對象都是不可變的(除非修改了對象來源),創(chuàng)建對象時需設置對象的相關屬性。所有對象都有相同的屬性。如下所示:
- 唯一的標識符
UUID
- 數(shù)據(jù)來源
source
9.0版本后用sourceRevision
-
device
生成這個對象數(shù)據(jù)的設備。 -
Metadata
用來描述對象的額外信息,是NSDictionary
類型,其中Key
都為NSString
類型,Value
可以為NSString
,NSNumber
,NSDate
類型。其中Key
可以為系統(tǒng)預定義的也可以自定義。系統(tǒng)預定義的Key
:
- 唯一的標識符
NSString * const HKMetadataKeyDeviceSerialNumber;
NSString * const HKMetadataKeyBodyTemperatureSensorLocation;
NSString * const HKMetadataKeyHeartRateSensorLocation;
NSString * const HKMetadataKeyFoodType;
NSString * const HKMetadataKeyUDIDeviceIdentifier;
NSString * const HKMetadataKeyUDIProductionIdentifier;
NSString * const HKMetadataKeyDigitalSignature;
NSString * const HKMetadataKeyExternalUUID;
NSString * const HKMetadataKeyTimeZone;
NSString * const HKMetadataKeyDeviceName;
NSString * const HKMetadataKeyDeviceManufacturerName;
NSString * const HKMetadataKeyWasTakenInLab;
NSString * const HKMetadataKeyReferenceRangeLowerLimit;
NSString * const HKMetadataKeyReferenceRangeUpperLimit;
NSString * const HKMetadataKeyWasUserEntered;
NSString * const HKMetadataKeyWorkoutBrandName;
NSString * const HKMetadataKeyGroupFitness;
NSString * const HKMetadataKeyIndoorWorkout;
NSString * const HKMetadataKeyCoachedWorkout;
NSString * const HKMetadataKeySexualActivityProtectionUsed;
NSString * const HKMetadataKeyMenstrualCycleStart;
```
- HKObjectType是用來描述HKObject的類型。我們也不能直接使用,只能使用其子類來對數(shù)據(jù)類型進行區(qū)分。其子類有:
- 初始化類型子類的方法有:
+ (nullable HKQuantityType *)quantityTypeForIdentifier:(NSString *)identifier;
+ (nullable HKCategoryType *)categoryTypeForIdentifier:(NSString *)identifier;
+ (nullable HKCharacteristicType *)characteristicTypeForIdentifier:(NSString *)identifier;
+ (nullable HKCorrelationType *)correlationTypeForIdentifier:(NSString *)identifier;
- 系統(tǒng)預定義類型的
Identifiers
有:
/*--------------------------------*/
/* HKQuantityType Identifiers */
/*--------------------------------*/
// Body Measurements
HK_EXTERN NSString * const HKQuantityTypeIdentifierBodyMassIndex NS_AVAILABLE_IOS(8_0); // Scalar(Count), Discrete
HK_EXTERN NSString * const HKQuantityTypeIdentifierBodyFatPercentage NS_AVAILABLE_IOS(8_0); // Scalar(Percent, 0.0 - 1.0), Discrete
HK_EXTERN NSString * const HKQuantityTypeIdentifierHeight NS_AVAILABLE_IOS(8_0); // Length, Discrete
HK_EXTERN NSString * const HKQuantityTypeIdentifierBodyMass NS_AVAILABLE_IOS(8_0); // Mass, Discrete
HK_EXTERN NSString * const HKQuantityTypeIdentifierLeanBodyMass NS_AVAILABLE_IOS(8_0); // Mass, Discrete
// Fitness
HK_EXTERN NSString * const HKQuantityTypeIdentifierStepCount NS_AVAILABLE_IOS(8_0); // Scalar(Count), Cumulative
HK_EXTERN NSString * const HKQuantityTypeIdentifierDistanceWalkingRunning NS_AVAILABLE_IOS(8_0); // Length, Cumulative
HK_EXTERN NSString * const HKQuantityTypeIdentifierDistanceCycling NS_AVAILABLE_IOS(8_0); // Length, Cumulative
HK_EXTERN NSString * const HKQuantityTypeIdentifierBasalEnergyBurned NS_AVAILABLE_IOS(8_0); // Energy, Cumulative
HK_EXTERN NSString * const HKQuantityTypeIdentifierActiveEnergyBurned NS_AVAILABLE_IOS(8_0); // Energy, Cumulative
HK_EXTERN NSString * const HKQuantityTypeIdentifierFlightsClimbed NS_AVAILABLE_IOS(8_0); // Scalar(Count), Cumulative
HK_EXTERN NSString * const HKQuantityTypeIdentifierNikeFuel NS_AVAILABLE_IOS(8_0); // Scalar(Count), Cumulative
HK_EXTERN NSString * const HKQuantityTypeIdentifierAppleExerciseTime HK_AVAILABLE_IOS_WATCHOS(9_3, 2_2); // Time Cumulative
// Vitals
HK_EXTERN NSString * const HKQuantityTypeIdentifierHeartRate NS_AVAILABLE_IOS(8_0); // Scalar(Count)/Time, Discrete
HK_EXTERN NSString * const HKQuantityTypeIdentifierBodyTemperature NS_AVAILABLE_IOS(8_0); // Temperature, Discrete
HK_EXTERN NSString * const HKQuantityTypeIdentifierBasalBodyTemperature NS_AVAILABLE_IOS(9_0); // Basal Body Temperature, Discrete
HK_EXTERN NSString * const HKQuantityTypeIdentifierBloodPressureSystolic NS_AVAILABLE_IOS(8_0); // Pressure, Discrete
HK_EXTERN NSString * const HKQuantityTypeIdentifierBloodPressureDiastolic NS_AVAILABLE_IOS(8_0); // Pressure, Discrete
HK_EXTERN NSString * const HKQuantityTypeIdentifierRespiratoryRate NS_AVAILABLE_IOS(8_0); // Scalar(Count)/Time, Discrete
// Results
HK_EXTERN NSString * const HKQuantityTypeIdentifierOxygenSaturation NS_AVAILABLE_IOS(8_0); // Scalar (Percent, 0.0 - 1.0, Discrete
HK_EXTERN NSString * const HKQuantityTypeIdentifierPeripheralPerfusionIndex NS_AVAILABLE_IOS(8_0); // Scalar(Percent, 0.0 - 1.0), Discrete
HK_EXTERN NSString * const HKQuantityTypeIdentifierBloodGlucose NS_AVAILABLE_IOS(8_0); // Mass/Volume, Discrete
HK_EXTERN NSString * const HKQuantityTypeIdentifierNumberOfTimesFallen NS_AVAILABLE_IOS(8_0); // Scalar(Count), Cumulative
HK_EXTERN NSString * const HKQuantityTypeIdentifierElectrodermalActivity NS_AVAILABLE_IOS(8_0); // Conductance, Discrete
HK_EXTERN NSString * const HKQuantityTypeIdentifierInhalerUsage NS_AVAILABLE_IOS(8_0); // Scalar(Count), Cumulative
HK_EXTERN NSString * const HKQuantityTypeIdentifierBloodAlcoholContent NS_AVAILABLE_IOS(8_0); // Scalar(Percent, 0.0 - 1.0), Discrete
HK_EXTERN NSString * const HKQuantityTypeIdentifierForcedVitalCapacity NS_AVAILABLE_IOS(8_0); // Volume, Discrete
HK_EXTERN NSString * const HKQuantityTypeIdentifierForcedExpiratoryVolume1 NS_AVAILABLE_IOS(8_0); // Volume, Discrete
HK_EXTERN NSString * const HKQuantityTypeIdentifierPeakExpiratoryFlowRate NS_AVAILABLE_IOS(8_0); // Volume/Time, Discrete
// Nutrition
HK_EXTERN NSString * const HKQuantityTypeIdentifierDietaryFatTotal NS_AVAILABLE_IOS(8_0); // Mass, Cumulative
HK_EXTERN NSString * const HKQuantityTypeIdentifierDietaryFatPolyunsaturated NS_AVAILABLE_IOS(8_0); // Mass, Cumulative
HK_EXTERN NSString * const HKQuantityTypeIdentifierDietaryFatMonounsaturated NS_AVAILABLE_IOS(8_0); // Mass, Cumulative
HK_EXTERN NSString * const HKQuantityTypeIdentifierDietaryFatSaturated NS_AVAILABLE_IOS(8_0); // Mass, Cumulative
HK_EXTERN NSString * const HKQuantityTypeIdentifierDietaryCholesterol NS_AVAILABLE_IOS(8_0); // Mass, Cumulative
HK_EXTERN NSString * const HKQuantityTypeIdentifierDietarySodium NS_AVAILABLE_IOS(8_0); // Mass, Cumulative
HK_EXTERN NSString * const HKQuantityTypeIdentifierDietaryCarbohydrates NS_AVAILABLE_IOS(8_0); // Mass, Cumulative
HK_EXTERN NSString * const HKQuantityTypeIdentifierDietaryFiber NS_AVAILABLE_IOS(8_0); // Mass, Cumulative
HK_EXTERN NSString * const HKQuantityTypeIdentifierDietarySugar NS_AVAILABLE_IOS(8_0); // Mass, Cumulative
HK_EXTERN NSString * const HKQuantityTypeIdentifierDietaryEnergyConsumed NS_AVAILABLE_IOS(8_0); // Energy, Cumulative
HK_EXTERN NSString * const HKQuantityTypeIdentifierDietaryProtein NS_AVAILABLE_IOS(8_0); // Mass, Cumulative
HK_EXTERN NSString * const HKQuantityTypeIdentifierDietaryVitaminA NS_AVAILABLE_IOS(8_0); // Mass, Cumulative
HK_EXTERN NSString * const HKQuantityTypeIdentifierDietaryVitaminB6 NS_AVAILABLE_IOS(8_0); // Mass, Cumulative
HK_EXTERN NSString * const HKQuantityTypeIdentifierDietaryVitaminB12 NS_AVAILABLE_IOS(8_0); // Mass, Cumulative
HK_EXTERN NSString * const HKQuantityTypeIdentifierDietaryVitaminC NS_AVAILABLE_IOS(8_0); // Mass, Cumulative
HK_EXTERN NSString * const HKQuantityTypeIdentifierDietaryVitaminD NS_AVAILABLE_IOS(8_0); // Mass, Cumulative
HK_EXTERN NSString * const HKQuantityTypeIdentifierDietaryVitaminE NS_AVAILABLE_IOS(8_0); // Mass, Cumulative
HK_EXTERN NSString * const HKQuantityTypeIdentifierDietaryVitaminK NS_AVAILABLE_IOS(8_0); // Mass, Cumulative
HK_EXTERN NSString * const HKQuantityTypeIdentifierDietaryCalcium NS_AVAILABLE_IOS(8_0); // Mass, Cumulative
HK_EXTERN NSString * const HKQuantityTypeIdentifierDietaryIron NS_AVAILABLE_IOS(8_0); // Mass, Cumulative
HK_EXTERN NSString * const HKQuantityTypeIdentifierDietaryThiamin NS_AVAILABLE_IOS(8_0); // Mass, Cumulative
HK_EXTERN NSString * const HKQuantityTypeIdentifierDietaryRiboflavin NS_AVAILABLE_IOS(8_0); // Mass, Cumulative
HK_EXTERN NSString * const HKQuantityTypeIdentifierDietaryNiacin NS_AVAILABLE_IOS(8_0); // Mass, Cumulative
HK_EXTERN NSString * const HKQuantityTypeIdentifierDietaryFolate NS_AVAILABLE_IOS(8_0); // Mass, Cumulative
HK_EXTERN NSString * const HKQuantityTypeIdentifierDietaryBiotin NS_AVAILABLE_IOS(8_0); // Mass, Cumulative
HK_EXTERN NSString * const HKQuantityTypeIdentifierDietaryPantothenicAcid NS_AVAILABLE_IOS(8_0); // Mass, Cumulative
HK_EXTERN NSString * const HKQuantityTypeIdentifierDietaryPhosphorus NS_AVAILABLE_IOS(8_0); // Mass, Cumulative
HK_EXTERN NSString * const HKQuantityTypeIdentifierDietaryIodine NS_AVAILABLE_IOS(8_0); // Mass, Cumulative
HK_EXTERN NSString * const HKQuantityTypeIdentifierDietaryMagnesium NS_AVAILABLE_IOS(8_0); // Mass, Cumulative
HK_EXTERN NSString * const HKQuantityTypeIdentifierDietaryZinc NS_AVAILABLE_IOS(8_0); // Mass, Cumulative
HK_EXTERN NSString * const HKQuantityTypeIdentifierDietarySelenium NS_AVAILABLE_IOS(8_0); // Mass, Cumulative
HK_EXTERN NSString * const HKQuantityTypeIdentifierDietaryCopper NS_AVAILABLE_IOS(8_0); // Mass, Cumulative
HK_EXTERN NSString * const HKQuantityTypeIdentifierDietaryManganese NS_AVAILABLE_IOS(8_0); // Mass, Cumulative
HK_EXTERN NSString * const HKQuantityTypeIdentifierDietaryChromium NS_AVAILABLE_IOS(8_0); // Mass, Cumulative
HK_EXTERN NSString * const HKQuantityTypeIdentifierDietaryMolybdenum NS_AVAILABLE_IOS(8_0); // Mass, Cumulative
HK_EXTERN NSString * const HKQuantityTypeIdentifierDietaryChloride NS_AVAILABLE_IOS(8_0); // Mass, Cumulative
HK_EXTERN NSString * const HKQuantityTypeIdentifierDietaryPotassium NS_AVAILABLE_IOS(8_0); // Mass, Cumulative
HK_EXTERN NSString * const HKQuantityTypeIdentifierDietaryCaffeine NS_AVAILABLE_IOS(8_0); // Mass, Cumulative
HK_EXTERN NSString * const HKQuantityTypeIdentifierDietaryWater NS_AVAILABLE_IOS(9_0); // Volume, Cumulative
HK_EXTERN NSString * const HKQuantityTypeIdentifierUVExposure NS_AVAILABLE_IOS(9_0); // Scalar (Count), Discrete
/*--------------------------------*/
/* HKCategoryType Identifiers */
/*--------------------------------*/
HK_EXTERN NSString * const HKCategoryTypeIdentifierSleepAnalysis NS_AVAILABLE_IOS(8_0); // HKCategoryValueSleepAnalysis
HK_EXTERN NSString * const HKCategoryTypeIdentifierAppleStandHour NS_AVAILABLE_IOS(9_0); // HKCategoryValueAppleStandHour
HK_EXTERN NSString * const HKCategoryTypeIdentifierCervicalMucusQuality NS_AVAILABLE_IOS(9_0); // HKCategoryValueCervicalMucusQuality
HK_EXTERN NSString * const HKCategoryTypeIdentifierOvulationTestResult NS_AVAILABLE_IOS(9_0); // HKCategoryValueOvulationTestResult
HK_EXTERN NSString * const HKCategoryTypeIdentifierMenstrualFlow NS_AVAILABLE_IOS(9_0); // HKCategoryValueMenstrualFlow
HK_EXTERN NSString * const HKCategoryTypeIdentifierIntermenstrualBleeding NS_AVAILABLE_IOS(9_0); // (Spotting) HKCategoryValue
HK_EXTERN NSString * const HKCategoryTypeIdentifierSexualActivity NS_AVAILABLE_IOS(9_0); // HKCategoryValue
/*--------------------------------------*/
/* HKCharacteristicType Identifiers */
/*--------------------------------------*/
HK_EXTERN NSString * const HKCharacteristicTypeIdentifierBiologicalSex NS_AVAILABLE_IOS(8_0); // NSNumber (HKCharacteristicBiologicalSex)
HK_EXTERN NSString * const HKCharacteristicTypeIdentifierBloodType NS_AVAILABLE_IOS(8_0); // NSNumber (HKCharacteristicBloodType)
HK_EXTERN NSString * const HKCharacteristicTypeIdentifierDateOfBirth NS_AVAILABLE_IOS(8_0); // NSDate
HK_EXTERN NSString * const HKCharacteristicTypeIdentifierFitzpatrickSkinType NS_AVAILABLE_IOS(9_0); // HKFitzpatrickSkinType
/*-----------------------------------*/
/* HKCorrelationType Identifiers */
/*-----------------------------------*/
HK_EXTERN NSString * const HKCorrelationTypeIdentifierBloodPressure NS_AVAILABLE_IOS(8_0);
HK_EXTERN NSString * const HKCorrelationTypeIdentifierFood NS_AVAILABLE_IOS(8_0);
/*------------------------------*/
/* HKWorkoutType Identifier */
/*------------------------------*/
HK_EXTERN NSString * const HKWorkoutTypeIdentifier NS_AVAILABLE_IOS(8_0);
NS_ASSUME_NONNULL_END
- 其中我們常用的有 HKQuantityType , HKCategoryType也是我應用中用過的類型。
如何使用
- 創(chuàng)建一個工程取名為: HealthKit
- Xcode8.0 , iOS 10.0后需要在Info.plist文件中添加讀寫說明,是否感覺似曾相識,其實它和使用定位功能時,需要在Info.plist中添加說明一個道理。(Demo 中的說明只是告訴你相關描述對應的讀取或寫入操作而已,具體描述自己根據(jù)應用實際情況斟酌描述)如下圖所示:
- 在
TAGETS
->Capabilities
打開->HealthKit
如下圖所示:
這時工程將會自動將
HealthKit.framework
加入工程。
-
創(chuàng)建一個管理我們HealthKit相關操作的類:
ZHHealthManager
里面包含請求訪問HealthKit庫以及相關讀寫操作。-
ZHHealthManager.h
文件相關方法
-
#import <Foundation/Foundation.h>
#import <HealthKit/HealthKit.h>
typedef void (^ZHHealthKitFinishBlock) (BOOL success,NSError *error);
typedef void (^ZHHealthKitIntegerValueBlock)(NSInteger value, NSError *error);
@interface ZHHealthManager : NSObject
@property (nonatomic) HKHealthStore * healthStore;
+(ZHHealthManager *)shareZHHealthManager;
/**
* request Authorization To Share Data in HealthKit
*
* @param finish block
*/
-(void)requestAuthorizationToShareWithCompletion:(ZHHealthKitFinishBlock)finish;
/**
* Read User Age
*
* @param finish finish block.
*/
-(void)readUsersAgeWithFinish:(ZHHealthKitIntegerValueBlock)finish;
/**
* write height data into HealthKit
*
* @param height height `cm`
* @param unit unit Option
* @param finish block
*/
-(void)saveHeightIntoHealthStore:(double)height withCompletion:(ZHHealthKitFinishBlock)finish;
/**
* write weight data into HealthKit
*
* @param weight weight `kg`
* @param unit unit option
* @param finish finishBlock
*/
-(void)saveWeightIntoHealthStore:(double)weight withCompletion:(ZHHealthKitFinishBlock)finish;
/**
* save stepcount into HealthKit
*
* @param steps steps
* @param startDate startDate
* @param endDate endDate
* @param finish Block
*/
-(void)saveStepCount:(NSInteger)steps startTime:(NSDate *)startDate endTime:(NSDate *)endDate withCompletion:(ZHHealthKitFinishBlock)finish;
/**
* save walk distance into healthKit
*
* @param walkDistance walk distance
* @param startDate startDate
* @param endDate endDate
* @param finish block
*/
-(void)saveWalkDistance:(double)walkDistance startTime:(NSDate *)startDate endTime:(NSDate *)endDate withCompletion:(ZHHealthKitFinishBlock)finish;
/**
* save active Energy burn calories into healthKit
*
* @param calories calories
* @param startDate startDate
* @param endDate endDate
* @param finish block
*/
-(void)saveActiveEnergyBurnCalories:(double)calories startTime:(NSDate *)startDate endTime:(NSDate *)endDate withCompletion:(ZHHealthKitFinishBlock)finish;
/**
* save heartRate into HealthKit
*
* @param heartRate heartRate
* @param finish block
*/
-(void)saveHeartRate:(NSInteger)heartRate withCompletion:(ZHHealthKitFinishBlock)finish;
/**
* save sleep data into HealthKit
*
* @param startDate start time
* @param endDate end time
* @param finish finish block
*/
-(void)saveSleepWithstartTime:(NSDate *)startDate endTime:(NSDate *)endDate withCompletion:(ZHHealthKitFinishBlock)finish;
@end
方法調(diào)用
- 首先我們需要把自己想要讀或寫的相關數(shù)據(jù)類型寫明。
#pragma mark - Health Kit TypesToWrite
-(NSSet *)dataTypesToWrite
{
HKQuantityType *stepCountQuantityType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount];
HKQuantityType *walkDistanceQuantityType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierDistanceWalkingRunning];
HKQuantityType *activeEnergyBurnQuantityType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierActiveEnergyBurned];
HKQuantityType *heartQuantityType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierHeartRate];
HKCategoryType *sleepCategoryType = [HKCategoryType categoryTypeForIdentifier:HKCategoryTypeIdentifierSleepAnalysis];
HKQuantityType *heightType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierHeight];
HKQuantityType *weightType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierBodyMass];
return [NSSet setWithObjects:stepCountQuantityType, walkDistanceQuantityType, activeEnergyBurnQuantityType,sleepCategoryType,heartQuantityType,heightType,weightType, nil];
}
#pragma mark - Health Kit TypesToRead
- (NSSet *)dataTypesToRead {
HKCharacteristicType *ageTypte = [HKObjectType characteristicTypeForIdentifier:HKCharacteristicTypeIdentifierDateOfBirth];
return [NSSet setWithObjects:ageTypte, nil];
}
- 然后申請訪問相關讀寫操作。
-(void)requestAuthorizationToShareWithCompletion:(ZHHealthKitFinishBlock)finish
{
if ([HKHealthStore isHealthDataAvailable]) {
NSSet *writeDataTypes = [self dataTypesToWrite];
NSSet *readDataTypes = [self dataTypesToRead];
[self.healthStore requestAuthorizationToShareTypes:writeDataTypes readTypes:readDataTypes completion:^(BOOL success, NSError *error){
if (finish) {
finish(success,error);
}
}];
}else{
NSDictionary *userInfo = @{NSLocalizedDescriptionKey: NSLocalizedString(@"健康應用不可用!", @"健康應用不可用!"),NSLocalizedFailureReasonErrorKey: NSLocalizedString(@"Health Kit not available.", @"Health Kit not available."),NSLocalizedRecoverySuggestionErrorKey: NSLocalizedString(@"Have you tried turning it off and on again?", @"Have you tried turning it off and on again?")};
NSError *error = [NSError errorWithDomain:NSPOSIXErrorDomain code:-10 userInfo:userInfo];
if (finish) {
finish(NO,error);
}
NSLog(@"Health Kit not available");
}
}
- 獲取權限后進行讀或寫相關操作,重要記住三點。
- 判斷系統(tǒng)版本,低于8.0不可用。
- 判斷設備是否支持HealthKit。
[HKHealthStore isHealthDataAvailable]
。 - 判斷用戶是否對這個類型的進行授權。
authorizationStatusForType
(基本不可變數(shù)據(jù)類型除外,例如:生日,性別,血型等)不對授權進行判斷,一般不會出問題在進行讀寫操作時也會有錯誤提示。但是對數(shù)據(jù)操作時系統(tǒng)判斷更耗時而且有時會出現(xiàn)莫名的錯誤。
- 這里舉兩個例子說明下:
- 對年齡進行讀操作。
- 對身高進行寫操作。
年齡讀操作
-(void)readUsersAgeWithFinish:(ZHHealthKitIntegerValueBlock)finish
{
NSInteger systemVersion = [[UIDevice currentDevice].systemVersion floatValue];
if (systemVersion <8.0){//系統(tǒng)少于8.0不可用
return;
}
if (![HKHealthStore isHealthDataAvailable])//健康不可用直接返回
{
return;
}
NSError *error;
NSDate *dateOfBirth = [self.healthStore dateOfBirthWithError:&error];
NSInteger age = -1;//年齡沒有獲取到返回-1
if (dateOfBirth) {//讀取到生日轉換成年齡
NSDate *now = [NSDate date];
NSDateComponents *ageComponents = [[NSCalendar currentCalendar] components:NSCalendarUnitYear fromDate:dateOfBirth toDate:now options:NSCalendarWrapComponents];
NSUInteger usersAge = [ageComponents year];
age = usersAge;
}
if (finish) {
finish(age,error);
}
}
身高寫操作
-(void)saveHeightIntoHealthStore:(double)height withCompletion:(ZHHealthKitFinishBlock)finish
{
NSInteger systemVersion = [[UIDevice currentDevice].systemVersion floatValue];
if (systemVersion <8.0){//系統(tǒng)少于8.0不可用
return;
}
if (![HKHealthStore isHealthDataAvailable])//健康不可用直接返回
{
return;
}
HKQuantityType *weightType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierBodyMass];
if ([self.healthStore authorizationStatusForType:weightType] != HKAuthorizationStatusSharingAuthorized) {
NSLog(@"未經(jīng)用戶允許訪問直接返回");
return;
}
HKUnit *hkUnit = [HKUnit inchUnit];
height = height/100;
hkUnit = [HKUnit meterUnit];
HKQuantity *heightQuantity = [HKQuantity quantityWithUnit:hkUnit doubleValue:height];
HKQuantityType *heightType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierHeight];
if ([self.healthStore authorizationStatusForType:heightType]) {
}
NSDate *now = [NSDate date];
HKQuantitySample *heightSample = [HKQuantitySample quantitySampleWithType:heightType quantity:heightQuantity startDate:now endDate:now];
[self.healthStore saveObject:heightSample withCompletion:^(BOOL success, NSError *error){
if (finish) {
finish(success, error);
}
}];
}
- 當然在進行其他樣本操作時,例如:記步,睡眠等等。如果有可能出現(xiàn)重復寫入,我們需要先進行判斷這段時間內(nèi)的數(shù)據(jù)是否已經(jīng)存入HealthKit。這里會用到查詢操作,具體可以參考我Demo中的
HKHealthStore+ZHHKExtensions
類。