December 17th, 2014
![]()
前言:
最近開始仔細瞭解HealthKit,發現使用上並沒有那麼的直覺.(可能是我對於許多醫療單位沒有那麼清楚的關係 XD) 使用上有一些要注意的與需要瞭解的部分,稍微做一些紀錄.
筆記:
[基本概念]
- 到目前為止,HealthKit只有iPhone可以用,並且要有iOS8.所以iPad執行程式會失敗.
- 每一個資料有所屬的資料格式數量(HKQuantity)與該數量的格式(HKQuantityType),而數量(Quantity)本身與單位的格式(HKUnit)有關.
- 必須要清楚地瞭解,存取的資料數量單位與單位的格式.
- 比如說,身高要確認是用cm還是inch,體重是使用pound還是kg.
- 每一個存取都與使用者權限有關,去拿使用者不開放的資料,就會引發錯誤.
- 所有的動作都是Async的方式:
- 這邊比較麻煩的是,如果需要抽象化的話可能要把async改成sync這邊可以參考這邊的內容.
[基本資料欄位]
- 關於資料欄位舉例而言,要敘述關於血壓的舒張壓,你就得要撰寫以下的部分:
//敘述你的血壓單位是 mmag mullumeter of mercyry unit
HKUnit *BPUnit = [HKUnit millimeterOfMercuryUnit];
//透過這個HKUnit去建立單位 HKQuantity
HKQuantity *BPSystolicQuantity = [HKQuantity quantityWithUnit:BPUnit doubleValue:SIS];
// 透過建立的單位與數值來建立這個單位類型(HKQuantityType)
HKQuantityType *BPSystolicType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierBloodPressureSystolic];
[取得使用者權限]
- 上面的方式僅僅是拿來作為處理資料欄位而已,接下來要開始去跟HealthKit查詢資料.在查詢資料之前,由於HealthKit上的資料都是儲存在手機上面,屬於個人私密資料.需要取得使用者的權限.
//取出體重單位格式
HKQuantityType *weightType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierBodyMass];
//取出身高單位格式
HKQuantityType *heightType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierHeight];
// 將身高體重加入要求的權限集合,這裡有分"讀取"與"寫入"的集合
NSSet *writeDataTypes = [NSSet setWithObjects:heightType, weightType, nil];
NSSet *readDataTypes = [NSSet setWithObjects:heightType, weightType, nil];
// 確認HealthKit 存不存在,這裡如果還是iPad 是不會有的,請注意.
if ([HKHealthStore isHealthDataAvailable]) {
// 要求使用者同意
[self.healthStore requestAuthorizationToShareTypes:writeDataTypes readTypes:readDataTypes completion:^(BOOL success, NSError *error) {
if (!success) {
NSLog(@"You didn't allow HealthKit to access these read/write data types. In your app, try to handle this error gracefully when a user decides not to provide access. The error was: %@. If you're using a simulator, try it on a device.", error);
return;
}
//處理成功以後,可能需要的資料讀取部分.
}];
}
[讀取資料]
- 關於讀取資料這邊,需要注意的就是必須要取得正確的單位.
- 還是一樣,讀到資料以後是async,所以可以用另外的thread來更新UI
- 以下提供取得”心跳(Heart Rate)”的方式
//心跳屬於複合資料欄位,需要用字串來找到HKUnit.文件不好找到.
HKUnit *dataUnit = [HKUnit unitFromString:@"count/min"];
//取得心跳的單位
HKQuantity *HRQuantity = [HKQuantity quantityWithUnit:dataUnit doubleValue:heartRate];
//取得心跳單位格式,注意HKQuantityTypeIdentifierHeartRate
HKQuantityType *HeartRateType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierHeartRate];
//建立資料回傳的sort敘述
NSSortDescriptor *timeSortDescriptor = [[NSSortDescriptor alloc] initWithKey:HKSampleSortIdentifierEndDate ascending:NO];
//建立查詢的指令,注意因為我們只需要最近的所以把limit設定成1
HKSampleQuery *query = [[HKSampleQuery alloc] initWithSampleType:HeartRateType predicate:nil limit:1 sortDescriptors:@[timeSortDescriptor] resultsHandler:^(HKSampleQuery *query, NSArray *results, NSError *error) {
if (!results) {
//錯誤發生
return;
}
//取得心跳資料
double usersHR = [mostRecentQuantity doubleValueForUnit:dataUnit];
}];
//執行查詢的指令
[self.healthStore executeQuery:query];
[寫入資料]
- 其實跟讀取一樣,主要也是要把HKUnit,HKQuantity與HKQuantityType搞定.
- 這邊需要注意的是,儲存的資料都是有時間格式的.你必須要設定開始時間與結束時間.
//建立心跳的單位
HKUnit *dataUnit = [HKUnit unitFromString:@"count/min"];
//建立心跳的數量單位
HKQuantity *HRQuantity = [HKQuantity quantityWithUnit:dataUnit doubleValue:heartRate];
//建立心跳的單位格式
HKQuantityType *HRType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierHeartRate];
NSDate *now = [NSDate date];
//建立數量取樣
HKQuantitySample *HRSample = [HKQuantitySample quantitySampleWithType:HRType
quantity:HRQuantity
startDate:now
endDate:now];
//存取該資料
[self.healthStore saveObject:HRSample withCompletion:^(BOOL success, NSError *error) {
if (!success) {
NSLog(@"An error occured saving the sample %@. In your app, try to handle this gracefully. The error was: %@.", dataQuantityType, error);
abort();
}
// 成功了之後,可以去更新資料.
[self some_UI_update];
}];