RCTAppleHealthKit+Methods_Body.m 12.8 KB
Newer Older
1 2 3 4 5
//
//  RCTAppleHealthKit+Methods_Body.m
//  RCTAppleHealthKit
//
//  Created by Greg Wilson on 2016-06-26.
6 7
//  This source code is licensed under the MIT-style license found in the
//  LICENSE file in the root directory of this source tree.
8 9 10 11
//

#import "RCTAppleHealthKit+Methods_Body.h"
#import "RCTAppleHealthKit+Queries.h"
12
#import "RCTAppleHealthKit+Utils.h"
13 14 15

@implementation RCTAppleHealthKit (Methods_Body)

Greg Wilson's avatar
Greg Wilson committed
16

17
- (void)body_getLatestWeight:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback
18 19 20
{
    HKQuantityType *weightType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierBodyMass];

Evgenii Evstropov's avatar
Evgenii Evstropov committed
21
    HKUnit *unit = [RCTAppleHealthKit hkUnitFromOptions:input key:@"unit" withDefault:[HKUnit gramUnitWithMetricPrefix:HKMetricPrefixKilo]];
22
    if(unit == nil){
23
        unit = [HKUnit gramUnit];
24 25
    }

26 27 28
    [self fetchMostRecentQuantitySampleOfType:weightType
                                    predicate:nil
                                   completion:^(HKQuantity *mostRecentQuantity, NSDate *startDate, NSDate *endDate, NSError *error) {
29
        if (!mostRecentQuantity) {
30 31
            NSLog(@"error getting latest weight: %@", error);
            callback(@[RCTMakeError(@"error getting latest weight", error, nil)]);
32 33 34
        }
        else {
            // Determine the weight in the required unit.
35
            double usersWeight = [mostRecentQuantity doubleValueForUnit:unit];
36 37 38 39 40 41 42
            NSDictionary *response = @{
                    @"value" : @(usersWeight),
                    @"startDate" : [RCTAppleHealthKit buildISO8601StringFromDate:startDate],
                    @"endDate" : [RCTAppleHealthKit buildISO8601StringFromDate:endDate],
            };

            callback(@[[NSNull null], response]);
43 44 45 46 47
        }
    }];
}


48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
- (void)body_getWeightSamples:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback
{
    HKQuantityType *weightType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierBodyMass];

    HKUnit *unit = [RCTAppleHealthKit hkUnitFromOptions:input key:@"unit" withDefault:[HKUnit poundUnit]];
    NSUInteger limit = [RCTAppleHealthKit uintFromOptions:input key:@"limit" withDefault:HKObjectQueryNoLimit];
    BOOL ascending = [RCTAppleHealthKit boolFromOptions:input key:@"ascending" withDefault:false];
    NSDate *startDate = [RCTAppleHealthKit dateFromOptions:input key:@"startDate" withDefault:nil];
    NSDate *endDate = [RCTAppleHealthKit dateFromOptions:input key:@"endDate" withDefault:[NSDate date]];
    if(startDate == nil){
        callback(@[RCTMakeError(@"startDate is required in options", nil, nil)]);
        return;
    }
    NSPredicate * predicate = [RCTAppleHealthKit predicateForSamplesBetweenDates:startDate endDate:endDate];

    [self fetchQuantitySamplesOfType:weightType
                                unit:unit
                           predicate:predicate
                           ascending:ascending
                               limit:limit
                          completion:^(NSArray *results, NSError *error) {
        if(results){
            callback(@[[NSNull null], results]);
            return;
        } else {
            NSLog(@"error getting weight samples: %@", error);
            callback(@[RCTMakeError(@"error getting weight samples", nil, nil)]);
            return;
        }
    }];
}


81 82
- (void)body_saveWeight:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback
{
83
    double weight = [RCTAppleHealthKit doubleValueFromOptions:input];
Terrillo Walls's avatar
Terrillo Walls committed
84
    NSDate *sampleDate = [RCTAppleHealthKit dateFromOptions:input key:@"startDate" withDefault:[NSDate date]];
85
    HKUnit *unit = [RCTAppleHealthKit hkUnitFromOptions:input key:@"unit" withDefault:[HKUnit poundUnit]];
86 87

    HKQuantity *weightQuantity = [HKQuantity quantityWithUnit:unit doubleValue:weight];
88
    HKQuantityType *weightType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierBodyMass];
89
    HKQuantitySample *weightSample = [HKQuantitySample quantitySampleWithType:weightType quantity:weightQuantity startDate:sampleDate endDate:sampleDate];
90 91 92

    [self.healthStore saveObject:weightSample withCompletion:^(BOOL success, NSError *error) {
        if (!success) {
93 94
            NSLog(@"error saving the weight sample: %@", error);
            callback(@[RCTMakeError(@"error saving the weight sample", error, nil)]);
95 96 97 98 99 100
            return;
        }
        callback(@[[NSNull null], @(weight)]);
    }];
}

101 102 103 104 105

- (void)body_getLatestBodyMassIndex:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback
{
    HKQuantityType *bmiType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierBodyMassIndex];

106 107 108
    [self fetchMostRecentQuantitySampleOfType:bmiType
                                    predicate:nil
                                   completion:^(HKQuantity *mostRecentQuantity, NSDate *startDate, NSDate *endDate, NSError *error) {
109
        if (!mostRecentQuantity) {
110 111
            NSLog(@"error getting latest BMI: %@", error);
            callback(@[RCTMakeError(@"error getting latest BMI", error, nil)]);
112 113 114 115 116 117
        }
        else {
            // Determine the bmi in the required unit.
            HKUnit *countUnit = [HKUnit countUnit];
            double bmi = [mostRecentQuantity doubleValueForUnit:countUnit];

118 119 120 121 122 123 124
            NSDictionary *response = @{
                    @"value" : @(bmi),
                    @"startDate" : [RCTAppleHealthKit buildISO8601StringFromDate:startDate],
                    @"endDate" : [RCTAppleHealthKit buildISO8601StringFromDate:endDate],
            };

            callback(@[[NSNull null], response]);
125 126 127 128 129
        }
    }];
}


130 131 132 133 134 135 136 137 138 139 140 141
- (void)body_saveBodyMassIndex:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback
{
    double bmi = [RCTAppleHealthKit doubleValueFromOptions:input];
    NSDate *sampleDate = [RCTAppleHealthKit dateFromOptionsDefaultNow:input];
    HKUnit *unit = [HKUnit countUnit];

    HKQuantity *bmiQuantity = [HKQuantity quantityWithUnit:unit doubleValue:bmi];
    HKQuantityType *bmiType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierBodyMassIndex];
    HKQuantitySample *bmiSample = [HKQuantitySample quantitySampleWithType:bmiType quantity:bmiQuantity startDate:sampleDate endDate:sampleDate];

    [self.healthStore saveObject:bmiSample withCompletion:^(BOOL success, NSError *error) {
        if (!success) {
142 143
            NSLog(@"error saving BMI sample: %@.", error);
            callback(@[RCTMakeError(@"error saving BMI sample", error, nil)]);
144 145 146 147 148 149 150
            return;
        }
        callback(@[[NSNull null], @(bmi)]);
    }];
}


151
- (void)body_getLatestHeight:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback
152 153 154
{
    HKQuantityType *heightType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierHeight];

Evgenii Evstropov's avatar
Evgenii Evstropov committed
155
    HKUnit *unit = [RCTAppleHealthKit hkUnitFromOptions:input key:@"unit" withDefault:[HKUnit meterUnitWithMetricPrefix:HKMetricPrefixCenti]];;
156
    if(unit == nil){
157
        unit = [HKUnit meterUnit];
158 159
    }

160 161 162
    [self fetchMostRecentQuantitySampleOfType:heightType
                                    predicate:nil
                                   completion:^(HKQuantity *mostRecentQuantity, NSDate *startDate, NSDate *endDate, NSError *error) {
163
        if (!mostRecentQuantity) {
164 165
            NSLog(@"error getting latest height: %@", error);
            callback(@[RCTMakeError(@"error getting latest height", error, nil)]);
166 167
        }
        else {
168
            // Determine the height in the required unit.
169 170 171 172 173 174 175 176 177
            double height = [mostRecentQuantity doubleValueForUnit:unit];

            NSDictionary *response = @{
                    @"value" : @(height),
                    @"startDate" : [RCTAppleHealthKit buildISO8601StringFromDate:startDate],
                    @"endDate" : [RCTAppleHealthKit buildISO8601StringFromDate:endDate],
            };

            callback(@[[NSNull null], response]);
178 179 180 181 182
        }
    }];
}


183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203
- (void)body_getHeightSamples:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback
{
    HKQuantityType *heightType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierHeight];

    HKUnit *unit = [RCTAppleHealthKit hkUnitFromOptions:input key:@"unit" withDefault:[HKUnit inchUnit]];
    NSUInteger limit = [RCTAppleHealthKit uintFromOptions:input key:@"limit" withDefault:HKObjectQueryNoLimit];
    BOOL ascending = [RCTAppleHealthKit boolFromOptions:input key:@"ascending" withDefault:false];
    NSDate *startDate = [RCTAppleHealthKit dateFromOptions:input key:@"startDate" withDefault:nil];
    NSDate *endDate = [RCTAppleHealthKit dateFromOptions:input key:@"endDate" withDefault:[NSDate date]];
    if(startDate == nil){
        callback(@[RCTMakeError(@"startDate is required in options", nil, nil)]);
        return;
    }
    NSPredicate * predicate = [RCTAppleHealthKit predicateForSamplesBetweenDates:startDate endDate:endDate];

    [self fetchQuantitySamplesOfType:heightType
                                unit:unit
                           predicate:predicate
                           ascending:ascending
                               limit:limit
                          completion:^(NSArray *results, NSError *error) {
204 205 206 207 208 209 210 211 212
        if(results){
          callback(@[[NSNull null], results]);
          return;
        } else {
          NSLog(@"error getting height samples: %@", error);
          callback(@[RCTMakeError(@"error getting height samples", error, nil)]);
          return;
        }
    }];
213 214 215
}


Greg Wilson's avatar
Greg Wilson committed
216 217 218 219 220
- (void)body_saveHeight:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback
{
    double height = [RCTAppleHealthKit doubleValueFromOptions:input];
    NSDate *sampleDate = [RCTAppleHealthKit dateFromOptionsDefaultNow:input];

Evgenii Evstropov's avatar
Evgenii Evstropov committed
221
    HKUnit *heightUnit = [RCTAppleHealthKit hkUnitFromOptions:input key:@"unit" withDefault:[HKUnit inchUnit]];;
222 223 224 225
    if(heightUnit == nil){
        heightUnit = [HKUnit inchUnit];
    }

Greg Wilson's avatar
Greg Wilson committed
226 227 228 229 230 231
    HKQuantity *heightQuantity = [HKQuantity quantityWithUnit:heightUnit doubleValue:height];
    HKQuantityType *heightType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierHeight];
    HKQuantitySample *heightSample = [HKQuantitySample quantitySampleWithType:heightType quantity:heightQuantity startDate:sampleDate endDate:sampleDate];

    [self.healthStore saveObject:heightSample withCompletion:^(BOOL success, NSError *error) {
        if (!success) {
232 233
            NSLog(@"error saving height sample: %@", error);
            callback(@[RCTMakeError(@"error saving height sample", error, nil)]);
Greg Wilson's avatar
Greg Wilson committed
234 235 236 237 238 239 240
            return;
        }
        callback(@[[NSNull null], @(height)]);
    }];
}


241
- (void)body_getLatestBodyFatPercentage:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback
242 243 244
{
    HKQuantityType *bodyFatPercentType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierBodyFatPercentage];

245 246 247
    [self fetchMostRecentQuantitySampleOfType:bodyFatPercentType
                                    predicate:nil
                                   completion:^(HKQuantity *mostRecentQuantity, NSDate *startDate, NSDate *endDate, NSError *error) {
248
        if (!mostRecentQuantity) {
249 250
            NSLog(@"error getting latest body fat percentage: %@", error);
            callback(@[RCTMakeError(@"error getting latest body fat percentage", error, nil)]);
251 252 253 254 255 256 257 258
        }
        else {
            // Determine the weight in the required unit.
            HKUnit *percentUnit = [HKUnit percentUnit];
            double percentage = [mostRecentQuantity doubleValueForUnit:percentUnit];

            percentage = percentage * 100;

259 260 261 262 263 264 265
            NSDictionary *response = @{
                    @"value" : @(percentage),
                    @"startDate" : [RCTAppleHealthKit buildISO8601StringFromDate:startDate],
                    @"endDate" : [RCTAppleHealthKit buildISO8601StringFromDate:endDate],
            };

            callback(@[[NSNull null], response]);
266 267 268 269 270
        }
    }];
}


271
- (void)body_getLatestLeanBodyMass:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback
272 273 274
{
    HKQuantityType *leanBodyMassType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierLeanBodyMass];

275 276 277
    [self fetchMostRecentQuantitySampleOfType:leanBodyMassType
                                    predicate:nil
                                   completion:^(HKQuantity *mostRecentQuantity, NSDate *startDate, NSDate *endDate, NSError *error) {
278
        if (!mostRecentQuantity) {
279 280
            NSLog(@"error getting latest lean body mass: %@", error);
            callback(@[RCTMakeError(@"error getting latest lean body mass", error, nil)]);
281 282 283 284 285
        }
        else {
            HKUnit *weightUnit = [HKUnit poundUnit];
            double leanBodyMass = [mostRecentQuantity doubleValueForUnit:weightUnit];

286 287 288 289 290 291 292
            NSDictionary *response = @{
                    @"value" : @(leanBodyMass),
                    @"startDate" : [RCTAppleHealthKit buildISO8601StringFromDate:startDate],
                    @"endDate" : [RCTAppleHealthKit buildISO8601StringFromDate:endDate],
            };

            callback(@[[NSNull null], response]);
293 294 295 296
        }
    }];
}

297
@end