HealthKit读取与修改步数

//
//  J_HelthKitViewController.m
//  ThirdFrameworksDemo
//
//  Created by jyf on 2018/5/15.
//  Copyright © 2018年 jyf. All rights reserved.
//

#import "J_HelthKitViewController.h"
#import <HealthKit/HealthKit.h>
#import <BlocksKit/UIControl+BlocksKit.h>
@interface J_HelthKitViewController ()

@property (nonatomic, strong)HKHealthStore *HKStore;
@property (nonatomic,strong) UILabel *countLabel;
@end
/*
 主要枚举:HKQuantityTypeIdentifierBodyMassIndex:体重指数
 HKQuantityTypeIdentifierBodyFatPercentage:体脂率
 HKQuantityTypeIdentifierHeight:身高
 HKQuantityTypeIdentifierBodyMass:体重
 HKQuantityTypeIdentifierLeanBodyMass:去脂体重
 HKQuantityTypeIdentifierStepCount:行走步数
 HKQuantityTypeIdentifierDistanceWalkingRunning:走跑距离
 HKQuantityTypeIdentifierDistanceCycling:骑行距离
 HKQuantityTypeIdentifierDistanceWheelchair:轮椅距离(喵喵喵?)
 HKQuantityTypeIdentifierBasalEnergyBurned:基础能量消耗/静息能量消耗
 HKQuantityTypeIdentifierActiveEnergyBurned:活动能量消耗
 HKQuantityTypeIdentifierFlightsClimbed:爬升距离/已爬楼层
 HKQuantityTypeIdentifierAppleExerciseTime:锻炼时间
 HKQuantityTypeIdentifierPushCount:推动次数
 HKQuantityTypeIdentifierDistanceSwimming:游泳距离  (这两项可能要手表数据,水果机不防水的吧
 HKQuantityTypeIdentifierSwimmingStrokeCount:划水次数
 
 HKQuantityTypeIdentifierHeartRate:心率
 HKQuantityTypeIdentifierBodyTemperature:体温
 HKQuantityTypeIdentifierBasalBodyTemperature 基础体温
 HKQuantityTypeIdentifierBloodPressureSystolic 收缩血压/高压
 HKQuantityTypeIdentifierBloodPressureDiastolic 舒张血压/低压
 HKQuantityTypeIdentifierRespiratoryRate:呼吸频率
 */

@implementation J_HelthKitViewController

#pragma mark -------------------------- viewDidLoad
- (void)viewDidLoad {
    [super viewDidLoad];
    [self function_setSubViews];
    [self function_getHealthKitAnthorization];
}

#pragma mark -------------------------- 添加字视图
- (void)function_setSubViews {
    self.countLabel = [[UILabel alloc]init];
    self.countLabel.textColor = [UIColor randomFlatColor];
    self.countLabel.font = [UIFont boldSystemFontOfSize:30];
    self.countLabel.numberOfLines = 0;
    self.countLabel.textAlignment = NSTextAlignmentCenter;
    [self.view addSubview:self.countLabel];
    [self.countLabel mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.right.mas_equalTo(10);
        make.top.mas_equalTo(100);
    }];
    
    UIButton *writeCountStepBtn = [UIButton buttonWithType:UIButtonTypeCustom];
    [writeCountStepBtn setTitle:@"写入步数" forState:UIControlStateNormal];
    [writeCountStepBtn bk_addEventHandler:^(id sender) {
        [self addstepWithStepNum:20000];
    } forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:writeCountStepBtn];
    
    [writeCountStepBtn mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.mas_equalTo(100);
        make.height.mas_equalTo(40);
        make.width.mas_equalTo(100);
        make.top.equalTo(self.countLabel.mas_bottom).offset(100);
    }];
}
#pragma mark -------------------------- 请求健康数据读写权限
- (void)function_getHealthKitAnthorization {
    self.HKStore = [[HKHealthStore alloc]init];
    //将你想查询的数据类型各自设置一个HKObjectTyoe,然后放进下面的NSSet中
    HKObjectType *stepType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount];//步数
    NSSet *healthSet = [NSSet setWithObjects:stepType, nil];
    
    HKObjectType *heartType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierHeartRate];//心率
    NSSet *readSet = [NSSet setWithObjects:heartType, nil];
    
    //shareTypesSet设置的是需要写入数据的NSset集合,readTypes设置的是读取数据的NSSet
    //返回结果中,如果success == true,则授权成功,开始进行读取操作
    [self.HKStore requestAuthorizationToShareTypes:readSet readTypes:readSet completion:^(BOOL success, NSError * _Nullable error) {
        if (success) {
            NSLog(@"success");
            [self function_requestData];
        }else{
            kLog(@"false-->%@",error);
        }
    }];
    [self.HKStore requestAuthorizationToShareTypes:healthSet readTypes:healthSet completion:^(BOOL success, NSError * _Nullable error) {
        if (success) {
            NSLog(@"success");
            [self function_requestData];
        }else{
            kLog(@"false-->%@",error);
        }
    }];

    
}
#pragma mark -------------------------- 整理数据,获取步数信息

- (void)function_requestData {
   
    //设置你需要查询的采样信息
    //所有的查询类都是基于抽象类HKQuery,这里我们用查询步数来举例,步数对应的类是HKSample类,所以我们需要实例化一个HKSampleQuery对象
    
    HKSampleType *sampleType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount];
    
    //NSSortDescriptor类是排序规则描述类,start规则描述了按照HKSample的运动开始时间startTimestamp降序排序
    //同理end描述了按照运动的结束时间endTimestamp降序排序
    //@[start end]的排序描述的规则是:首先按照运动开始时间排序,如果开始时间相同,则按照结束时间降序排序
    
    NSSortDescriptor *start = [NSSortDescriptor sortDescriptorWithKey:HKSampleSortIdentifierStartDate ascending:NO];
    NSSortDescriptor *end = [NSSortDescriptor sortDescriptorWithKey:HKSampleSortIdentifierEndDate ascending:NO];
    
    //设置查询时间
    
    NSDate *now = [NSDate date];
    NSCalendar *calender = [NSCalendar currentCalendar];
    
    NSUInteger unitFlags = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond;
    //将当前时间按照上述格式分割成年月日时分秒六个数字,然后提取时分秒
    
    NSDateComponents *dateComponent = [calender components:unitFlags fromDate:now];
    int hour = (int)[dateComponent hour];
    int minute = (int)[dateComponent minute];
    int second = (int)[dateComponent second];
    //当前时间点 减去今天已经过去的时分秒 加上东八区时差补偿 = 今天开始的00:00分
    NSDate *today = [NSDate dateWithTimeIntervalSinceNow:  - (hour*3600 + minute * 60 + second) + 28800];
    NSDate *tomorrow = [NSDate dateWithTimeIntervalSinceNow:  - (hour*3600 + minute * 60 + second) + 28800 + 86400];
    
    //设置查询范围为今天到明天的24小时内
    NSPredicate *predicate = [HKQuery predicateForSamplesWithStartDate:today endDate:tomorrow options:HKQueryOptionNone];
    HKSampleQuery *query = [[HKSampleQuery alloc]initWithSampleType:sampleType predicate:predicate limit:HKObjectQueryNoLimit sortDescriptors:@[start,end] resultsHandler:^(HKSampleQuery * _Nonnull query, NSArray<__kindof HKSample *> * _Nullable results, NSError * _Nullable error) {
      
        if (results.count > 0) {
            kLog(@"查询成功-->%@",results);
            NSInteger count = 0;
            
            for (HKQuantitySample *sample in results) {
                
                NSString *str = [NSString stringWithFormat:@"%@",sample.quantity];
                kLog(@"%@",str);
                NSString *str2 = [str componentsSeparatedByString:@" "][0];
                NSInteger step = [str2 integerValue];
                count += step;
                
            }
            dispatch_async(dispatch_get_main_queue(), ^{
                self.countLabel.text = [NSString stringWithFormat:@"截至目前\r\n今天共走了-->%ld步",count];
            });
            kLog(@"截至目前,共走了-->%ld 步",count);
            
        }
    }];
    
    [self.HKStore executeQuery:query];
    
}
#pragma mark - **************** 写入步数

- (void)addstepWithStepNum:(double)stepNum {
    // Create a new food correlation for the given food item.
    HKQuantitySample *stepCorrelationItem = [self stepCorrelationWithStepNum:stepNum];
    
    [self.HKStore saveObject:stepCorrelationItem withCompletion:^(BOOL success, NSError *error) {
        dispatch_async(dispatch_get_main_queue(), ^{
            if (success) {
                [self.view endEditing:YES];
                UIAlertView *doneAlertView = [[UIAlertView alloc] initWithTitle:@"提示" message:@"添加成功" delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil, nil];
                [doneAlertView show];
            }
            else {
                NSLog(@"The error was: %@.", error);
                UIAlertView *doneAlertView = [[UIAlertView alloc] initWithTitle:@"提示" message:@"添加失败" delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil, nil];
                [doneAlertView show];
                return ;
            }
        });
    }];
}

- (HKQuantitySample *)stepCorrelationWithStepNum:(double)stepNum {
    NSDate *endDate = [NSDate date];
    NSDate *startDate = [NSDate dateWithTimeInterval:-300 sinceDate:endDate];
    
    HKQuantity *stepQuantityConsumed = [HKQuantity quantityWithUnit:[HKUnit countUnit] doubleValue:stepNum];
    
    HKQuantityType *stepConsumedType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount];
    
    HKDevice *device = [[HKDevice alloc] initWithName:@"iPhone" manufacturer:@"Apple" model:@"iPhone" hardwareVersion:@"iPhone6s plus" firmwareVersion:@"iPhone6s plus" softwareVersion:@"9.3.1" localIdentifier:@"aaron" UDIDeviceIdentifier:@"aaron"];
    //    NSDictionary *stepCorrelationMetadata = @{HKMetadataKeyUDIDeviceIdentifier: @"aaron's test equipment",
    //                                                  HKMetadataKeyDeviceName:@"iPhone",
    //                                                  HKMetadataKeyWorkoutBrandName:@"Apple",
    //                                                  HKMetadataKeyDeviceManufacturerName:@"Apple"};
    HKQuantitySample *stepConsumedSample = [HKQuantitySample quantitySampleWithType:stepConsumedType quantity:stepQuantityConsumed startDate:startDate endDate:endDate device:device metadata:nil];
    return stepConsumedSample;
}


- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

/*
#pragma mark - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    // Get the new view controller using [segue destinationViewController].
    // Pass the selected object to the new view controller.
}
*/

@end

推荐阅读更多精彩内容