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]; }];