如何通过Health Kit将健康记录添加到健康应用程序

时间:2018-02-09 07:53:49

标签: objective-c health-kit

我能够在健康应用程序中读取样本数据,如身体质量,身高,体重,并从年龄,性别,血型等资料中读取。我的代码请求身份验证和读/写方法如下

- (void)requestAuthorization {

    if ([HKHealthStore isHealthDataAvailable] == NO) {
        // If our device doesn't support HealthKit -> return.
        return;
    }

    HKObjectType *dateOfBirth = [HKObjectType characteristicTypeForIdentifier:HKCharacteristicTypeIdentifierDateOfBirth];
    HKObjectType *bloodType = [HKObjectType characteristicTypeForIdentifier:HKCharacteristicTypeIdentifierBloodType];
    HKObjectType *biologicalSex = [HKObjectType characteristicTypeForIdentifier:HKCharacteristicTypeIdentifierBiologicalSex];
    HKObjectType *wheelChairUse = [HKObjectType characteristicTypeForIdentifier:HKCharacteristicTypeIdentifierWheelchairUse];
    HKObjectType *skinType = [HKObjectType characteristicTypeForIdentifier:HKCharacteristicTypeIdentifierFitzpatrickSkinType];

    HKObjectType *bodyMassIndex = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierBodyMassIndex];
    HKObjectType *height = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierHeight];
    HKObjectType *bodyMass = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierBodyMass];
    HKObjectType *activeEnergy = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierActiveEnergyBurned];

    HKObjectType *heartRate = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierHeartRate];
    HKObjectType *bloodGlucose = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierBloodGlucose];
    HKObjectType *bodyTemprature = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierBodyTemperature];
    HKObjectType *respiratoryRate = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierRespiratoryRate];
    HKObjectType *oxygenSaturation = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierOxygenSaturation];
    HKObjectType *fatPercentage = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierBodyFatPercentage];
    HKObjectType *waistCircumference = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierWaistCircumference];
    HKObjectType *cholestrol = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierDietaryCholesterol];


    NSArray *healthKitTypesToWrite = @[bodyMassIndex,
                                       activeEnergy,
                                       HKObjectType.workoutType];

    NSArray *healthKitTypesToRead = @[dateOfBirth,
                                      bloodType,
                                      biologicalSex,
                                      bodyMassIndex,
                                      height,
                                      bodyMass,
                                      wheelChairUse,
                                      skinType,
                                      heartRate,
                                      bloodGlucose,
                                      bodyTemprature,
                                      respiratoryRate,
                                      oxygenSaturation,
                                      fatPercentage,
                                      waistCircumference,
                                      cholestrol,
                                      HKObjectType.workoutType];

    [self.healthStore requestAuthorizationToShareTypes:[NSSet setWithArray:healthKitTypesToWrite] readTypes:[NSSet setWithArray:healthKitTypesToRead] completion:^(BOOL success, NSError * _Nullable error) {

    }];
}

pragma mark- Helper

- (void )getMostRecentSampleForType:(HKSampleType *)sampleType
                  withResultHandler:(HKQueryResultHandler )handler {

    NSPredicate *mostRecentPredicate = [HKQuery predicateForSamplesWithStartDate:NSDate.distantPast endDate:[NSDate date] options:HKQueryOptionStrictEndDate];
    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:HKSampleSortIdentifierStartDate ascending:false];
    NSInteger limit = 1;

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

        dispatch_async(dispatch_get_main_queue(), ^{
            // do work here
            if (handler) {
                if (results && results.count > 0) {
                    HKQuantitySample *sample = (HKQuantitySample *)[results firstObject];
                    handler(sample,nil);
                }else {
                    handler(nil,error);
                }
            }
        });
    }];

    HKHealthStore *store = [[HKHealthStore alloc] init];
    [store executeQuery:sampleQuery];
}

pragma mark-读取方法

- (NSDate *)readBirthDate {
    NSError *error;

    NSDateComponents *components = [self.healthStore dateOfBirthComponentsWithError:&error];
    // Convenience method of HKHealthStore to get date of birth directly.

    NSCalendar *cal = [NSCalendar currentCalendar];
    [cal setTimeZone:[NSTimeZone localTimeZone]];
    [cal setLocale:[NSLocale currentLocale]];
    NSDate *dateOfBirth = [cal dateFromComponents:components];

    if (!dateOfBirth) {
        NSLog(@"Either an error occured fetching the user's age information or none has been stored yet. In your app, try to handle this gracefully.");
    }
    return dateOfBirth;
}

- (NSString *)biologicalSex {
    HKBiologicalSexObject *genderObj = [self.healthStore biologicalSexWithError:nil];
    HKBiologicalSex gender = genderObj.biologicalSex;

    switch (gender) {
        case HKBiologicalSexNotSet:
            return @"";
        case HKBiologicalSexFemale:
            return @"Female";
        case HKBiologicalSexMale:
            return @"Male";
        case HKBiologicalSexOther:
            return @"Other";
        default:
            break;
    }
    return @"";
}

- (NSString *)weight {
    HKSampleType *weightSampleType = [HKSampleType quantityTypeForIdentifier:HKQuantityTypeIdentifierBodyMass];
    [self getMostRecentSampleForType:weightSampleType withResultHandler:^(HKQuantitySample *sample, NSError *error) {
        if (!errno) {
            HKQuantity *quantity = sample.quantity;
            HKUnit *kilogramUnit = [HKUnit gramUnitWithMetricPrefix:HKMetricPrefixKilo];
            double weight = [quantity doubleValueForUnit:kilogramUnit];
            NSLog(@"weight = %.0f Kg",weight);
        }
    }];
    return @"";
}

pragma mark-write方法

- (void)writeWeightSample:(CGFloat)weight {

    // Each quantity consists of a value and a unit.
    HKUnit *kilogramUnit = [HKUnit gramUnitWithMetricPrefix:HKMetricPrefixKilo];
    HKQuantity *weightQuantity = [HKQuantity quantityWithUnit:kilogramUnit doubleValue:weight];

    HKQuantityType *weightType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierBodyMass];
    NSDate *now = [NSDate date];

    // For every sample, we need a sample type, quantity and a date.
    HKQuantitySample *weightSample = [HKQuantitySample quantitySampleWithType:weightType quantity:weightQuantity startDate:now endDate:now];

    [self.healthStore saveObject:weightSample withCompletion:^(BOOL success, NSError *error) {
        if (!success) {
            NSLog(@"Error while saving weight (%f) to Health Store: %@.", weight, error);
        }
    }];
}

但我没有找到任何关于如何在Health Data - &gt; Health Records

中添加记录的线索

Health Record

No Data

3 个答案:

答案 0 :(得分:1)

Apple正在使用此部分显示使用CDA文件检索的数据。 CDA是一种允许医疗服务提供者之间互操作的标准。您可能能够从您的医疗服务提供者患者门户网站下载您自己的CDA。

没有很多应用程序会将CDA文件导入HealthKit,但apple有一个代码示例,它将创建一个虚拟CDA文件并将其导入HealthKit

从app中查看LoopHealth示例 https://developer.apple.com/library/content/samplecode/LoopHealth/Introduction/Intro.html#//apple_ref/doc/uid/TP40017553-Intro-DontLinkElementID_2

答案 1 :(得分:0)

// 1. Create a BMI Sample
let bmiType = HKQuantityType.quantityType(forIdentifier: HKQuantityTypeIdentifier.bodyMassIndex)
let bmiQuantity = HKQuantity(unit: HKUnit.count(), doubleValue: bmi)
let bmiSample = HKQuantitySample(type: bmiType!, quantity: bmiQuantity, start: date as Date, end: date as Date)

// 2. Save the sample in the store
healthKitStore.save(bmiSample, withCompletion: { (success, error) -> Void in
    if( error != nil ) {
        print("Error saving BMI sample: \(String(describing: error?.localizedDescription))")
    } else {
        print("BMI sample saved successfully!")
    }
})

答案 2 :(得分:0)

我不熟悉HL7和CDA Pro,因为我不属于健康产业。因此,我无法使用适当的条目添加codeSystemcodecodeSystemName等。虽然我找到了一种方法来生成自定义的CDA文件,只是为了显示在健康记录中。

您需要将占位符CDA文件保留在资源包中。 visitSummary.xml

- (void)addToHealth {      

    NSURL *cdaURL = [[NSBundle mainBundle] URLForResource:@"visitSummary" withExtension:@"xml"];
    NSError *parsingError = nil;
    NSString *string = [NSString stringWithContentsOfURL:cdaURL encoding:NSUTF8StringEncoding error:&parsingError];

    string = [string stringByReplacingOccurrencesOfString:@"DOCUMENT_ID" withString:@"DOC449"];
    string = [string stringByReplacingOccurrencesOfString:@"PAT_NAME" withString:@"Alan Joseph"];
    string = [string stringByReplacingOccurrencesOfString:@"MOBILE_NO" withString:@"9643453174"];
    string = [string stringByReplacingOccurrencesOfString:@"EMAIL_ID" withString:@"alan28.joseph@gmail.com"];
    string = [string stringByReplacingOccurrencesOfString:@"PATIENT_ID" withString:@"PID242000012"];
    string = [string stringByReplacingOccurrencesOfString:@"DATE_OF_BIRTH" withString:@"19920515"];

    string = [string stringByReplacingOccurrencesOfString:@"PAT_STREET_LINE" withString:@"Prithviraj Market, Khan Market"];
    string = [string stringByReplacingOccurrencesOfString:@"PAT_CITY" withString:@"New Delhi"];
    string = [string stringByReplacingOccurrencesOfString:@"PAT_STATE" withString:@"Delhi"];
    string = [string stringByReplacingOccurrencesOfString:@"PAT_POSTAL" withString:@"110003"];

    string = [string stringByReplacingOccurrencesOfString:@"GENDER_CODE" withString:@"M"];
    string = [string stringByReplacingOccurrencesOfString:@"GENDER_DISPLAY" withString:@"Male"];

    string = [string stringByReplacingOccurrencesOfString:@"MODEL_NAME" withString:@"iPad Air"];
    string = [string stringByReplacingOccurrencesOfString:@"AUTHOR_NAME" withString:@"Mark"];
    string = [string stringByReplacingOccurrencesOfString:@"CUSTODIAN_NAME" withString:@"Dr. Lauren"];

    string = [string stringByReplacingOccurrencesOfString:@"ALLERGY_COMPONENTS" withString:[self allergyComponents]];
    string = [string stringByReplacingOccurrencesOfString:@"FAMILY_HISTORY_COMPONENTS" withString:[self familyHistoryComponents]];
        string = [string stringByReplacingOccurrencesOfString:@"VITALS_COMPONENTS" withString:[self vitalSignsComponents]];

    NSData *cdaData = [string dataUsingEncoding:NSUTF8StringEncoding];

    NSError *validationError = nil;
    NSDate *date = [NSDate date];
    HKSample *cdaSample = [HKCDADocumentSample CDADocumentSampleWithData:cdaData startDate:date endDate:date metadata:nil validationError:&validationError];

    if (cdaSample != nil) {
        [self.healthStore saveObject:cdaSample withCompletion:^(BOOL success, NSError * _Nullable error) {
            if (!success) {
                NSLog(@"Error while saving CDA to Health Store: %@.", error);
            }
        }];
    }else {
        NSLog(@"No records");
    }
}

虽然您需要再添加一个HKObjectType请求,即; CDA文件。

HKObjectType *cdaObjType = [HKObjectType documentTypeForIdentifier:HKDocumentTypeIdentifierCDA];

NSArray *healthKitTypesToWrite = @[bodyMassIndex,
                                   activeEnergy,
                                   cdaObjType,
                                   HKObjectType.workoutType];

NSArray *healthKitTypesToRead = @[dateOfBirth,
                                  bloodType,
                                  biologicalSex,
                                  bodyMassIndex,
                                  height,
                                  bodyMass,
                                  wheelChairUse,
                                  skinType,
                                  heartRate,
                                  bloodGlucose,
                                  bodyTemprature,
                                  respiratoryRate,
                                  oxygenSaturation,
                                  fatPercentage,
                                  waistCircumference,
                                  cholestrol,
                                  cdaObjType,
                                  HKObjectType.workoutType];

[self.healthStore requestAuthorizationToShareTypes:[NSSet setWithArray:healthKitTypesToWrite] readTypes:[NSSet setWithArray:healthKitTypesToRead] completion:^(BOOL success, NSError * _Nullable error) {

}];

帮助准备组件的方法。

- (NSString *)allergyComponents {

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

    [allergyComponents addObject:@"<component>"];
    [allergyComponents addObject:@"<section>"];
    [allergyComponents addObject:@"<title>Allergies</title>"];
    [allergyComponents addObject:@"<text>"];
    [allergyComponents addObject:@"<table border=\"1\" width=\"100%\">"];

    [allergyComponents addObject:@"<thead><tr>"];
    [allergyComponents addObject:@"<th>Name</th>"];
    [allergyComponents addObject:@"<th>Type</th>"];
    [allergyComponents addObject:@"<th>Exists From</th>"];
    [allergyComponents addObject:@"</tr></thead>"];
    [allergyComponents addObject:@"<tbody>"];

    for (int i = 0; i<3; i++) {
        [allergyComponents addObject:@"<tr>"];
        [allergyComponents addObject:@"<td>Abalone,perlemoen</td>"];
        [allergyComponents addObject:@"<td>Food Allergy</td>"];
        [allergyComponents addObject:@"<td>29 Feb</td>"];
        [allergyComponents addObject:@"</tr>"];
    }

    [allergyComponents addObject:@"</tbody>"];
    [allergyComponents addObject:@"</table>"];
    [allergyComponents addObject:@"</text>"];
    [allergyComponents addObject:@"</section>"];
    [allergyComponents addObject:@"</component>"];

    return [allergyComponents componentsJoinedByString:@""];
}

- (NSString *)familyHistoryComponents {

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

    [familyComponents addObject:@"<component>"];
    [familyComponents addObject:@"<section>"];
    [familyComponents addObject:@"<title>Family History</title>"];
    [familyComponents addObject:@"<text>"];
    [familyComponents addObject:@"<table border=\"1\" width=\"100%\">"];

    [familyComponents addObject:@"<thead><tr>"];
    [familyComponents addObject:@"<th>Relation</th>"];
    [familyComponents addObject:@"<th>Condition</th>"];
    [familyComponents addObject:@"</tr></thead>"];
    [familyComponents addObject:@"<tbody>"];

    for (int i = 0; i<2; i++) {
        [familyComponents addObject:@"<tr>"];
        [familyComponents addObject:@"<td>Father</td>"];
        [familyComponents addObject:@"<td>A, Hemophilia</td>"];
        [familyComponents addObject:@"</tr>"];
    }

    [familyComponents addObject:@"</tbody>"];
    [familyComponents addObject:@"</table>"];
    [familyComponents addObject:@"</text>"];
    [familyComponents addObject:@"</section>"];
    [familyComponents addObject:@"</component>"];

    return [familyComponents componentsJoinedByString:@""];
}

- (NSString *)vitalSignsComponents {

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

    [vitalSigns addObject:@"<component>"];
    [vitalSigns addObject:@"<section>"];
    [vitalSigns addObject:@"<title>Vital Signs</title>"];
    [vitalSigns addObject:@"<text>"];
    [vitalSigns addObject:@"<table border=\"1\" width=\"100%\">"];

    [vitalSigns addObject:@"<thead><tr>"];
    [vitalSigns addObject:@"<th align=\"right\">Date</th>"];
    [vitalSigns addObject:@"<th>Vital</th>"];
    [vitalSigns addObject:@"<th>Reading</th>"];
    [vitalSigns addObject:@"</tr></thead>"];
    [vitalSigns addObject:@"<tbody>"];

    for (int i = 0; i<2; i++) {
        [vitalSigns addObject:@"<tr>"];
        [vitalSigns addObject:@"<th align=\"left\">26-10-2017</th>"];
        [vitalSigns addObject:@"<td>Pulse</td>"];
        [vitalSigns addObject:@"<td>12 bpm</td>"];
        [vitalSigns addObject:@"</tr>"];
    }

    [vitalSigns addObject:@"</tbody>"];
    [vitalSigns addObject:@"</table>"];
    [vitalSigns addObject:@"</text>"];
    [vitalSigns addObject:@"</section>"];
    [vitalSigns addObject:@"</component>"];

    return [vitalSigns componentsJoinedByString:@""];
}

这是输出健康应用程序中的样子。

enter image description here

预览看起来像。

enter image description here