iOS开发-读取“健康”中的步数和步行+跑步距离

2023-11-22 15:10

本文主要是介绍iOS开发-读取“健康”中的步数和步行+跑步距离,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

借鉴于
http://www.csdn.net/article/2015-01-23/2823686-healthkit-tutorial-with-swift/4

  • 注:iOS10遇到的错误:
    Terminating app due to uncaught exception 'NSInvalidArgumentException',
    reason: 'NSHealthUpdateUsageDescription must be set in the app's Info.plist
    in order to request write authorization.'
    解决办法:
    我们要在info.plist文件中声明苹果健康的使用权限,所以在info.plist中添加以下key就可以了。请求写入和请求读取都需要添加!
    请求写入
    <key>NSHealthUpdateUsageDescription</key>
    <string>some string value stating the reason</string>
    请求读取
    <key>NSHealthShareUsageDescription</key><string>some string value stating the reason</string>
    从iOS 10 因苹果健康导致闪退 crash - 借鉴与简书作者文章 找到的解决办法,谢谢

1、第一步首先需要开启HealthKit


HealthKit.png

2、新建一个HealthKitManage类,继承于NSObject

  • (1)首先在.h文件里面声明一个属性
@property (nonatomic, strong) HKHealthStore *healthStore;
  • (2)导入头文件
#import <HealthKit/HealthKit.h>
#import <UIKit/UIDevice.h>#define HKVersion [[[UIDevice currentDevice] systemVersion] doubleValue]
#define CustomHealthErrorDomain @"com.sdqt.healthError"
  • (3)创建单例方法
+(id)shareInstance
{static id manager ;static dispatch_once_t onceToken;dispatch_once(&onceToken, ^{manager = [[[self class] alloc] init];});return manager;
}
  • (4)检查是否支持获取健康数据
/**  @brief  检查是否支持获取健康数据*/
- (void)authorizeHealthKit:(void(^)(BOOL success, NSError *error))compltion
{if(HKVersion >= 8.0){if (![HKHealthStore isHealthDataAvailable]) {NSError *error = [NSError errorWithDomain: @"com.raywenderlich.tutorials.healthkit" code: 2 userInfo: [NSDictionary dictionaryWithObject:@"HealthKit is not available in th is Device"                                                                      forKey:NSLocalizedDescriptionKey]];if (compltion != nil) {compltion(false, error);}return;}if ([HKHealthStore isHealthDataAvailable]) {if(self.healthStore == nil)self.healthStore = [[HKHealthStore alloc] init];/*组装需要读写的数据类型*/NSSet *writeDataTypes = [self dataTypesToWrite];NSSet *readDataTypes = [self dataTypesRead];/*注册需要读写的数据类型,也可以在“健康”APP中重新修改*/[self.healthStore requestAuthorizationToShareTypes:writeDataTypes readTypes:readDataTypes completion:^(BOOL success, NSError *error) {if (compltion != nil) {NSLog(@"error->%@", error.localizedDescription);compltion (success, error);}}];}}else {NSDictionary *userInfo = [NSDictionary dictionaryWithObject:@"iOS 系统低于8.0"                                                                      forKey:NSLocalizedDescriptionKey];NSError *aError = [NSError errorWithDomain:CustomHealthErrorDomain code:0 userInfo:userInfo];compltion(0,aError);}
}/*!*  @brief  写权限*  @return 集合*/
- (NSSet *)dataTypesToWrite
{HKQuantityType *heightType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierHeight];HKQuantityType *weightType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierBodyMass];HKQuantityType *temperatureType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierBodyTemperature];HKQuantityType *activeEnergyType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierActiveEnergyBurned];return [NSSet setWithObjects:heightType, temperatureType, weightType,activeEnergyType,nil];
}/*!*  @brief  读权限*  @return 集合*/
- (NSSet *)dataTypesRead
{HKQuantityType *heightType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierHeight];HKQuantityType *weightType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierBodyMass];HKQuantityType *temperatureType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierBodyTemperature];HKCharacteristicType *birthdayType = [HKObjectType characteristicTypeForIdentifier:HKCharacteristicTypeIdentifierDateOfBirth];HKCharacteristicType *sexType = [HKObjectType characteristicTypeForIdentifier:HKCharacteristicTypeIdentifierBiologicalSex];HKQuantityType *stepCountType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount];HKQuantityType *distance = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierDistanceWalkingRunning];HKQuantityType *activeEnergyType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierActiveEnergyBurned];return [NSSet setWithObjects:heightType, temperatureType,birthdayType,sexType,weightType,stepCountType, distance, activeEnergyType,nil];
}
  • (5)读取步数
//获取步数
- (void)getStepCount:(void(^)(double value, NSError *error))completion
{HKQuantityType *stepType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount];NSSortDescriptor *timeSortDescriptor = [[NSSortDescriptor alloc] initWithKey:HKSampleSortIdentifierEndDate ascending:NO];// Since we are interested in retrieving the user's latest sample, we sort the samples in descending order, and set the limit to 1. We are not filtering the data, and so the predicate is set to nil.HKSampleQuery *query = [[HKSampleQuery alloc] initWithSampleType:stepType predicate:[HealthKitManage predicateForSamplesToday] limit:HKObjectQueryNoLimit sortDescriptors:@[timeSortDescriptor] resultsHandler:^(HKSampleQuery *query, NSArray *results, NSError *error) {if(error){completion(0,error);}else{NSInteger totleSteps = 0;for(HKQuantitySample *quantitySample in results){HKQuantity *quantity = quantitySample.quantity;HKUnit *heightUnit = [HKUnit countUnit];double usersHeight = [quantity doubleValueForUnit:heightUnit];totleSteps += usersHeight;}NSLog(@"当天行走步数 = %ld",(long)totleSteps);completion(totleSteps,error);}}];[self.healthStore executeQuery:query];
}
  • (6)读取步行+跑步距离
//获取公里数
- (void)getDistance:(void(^)(double value, NSError *error))completion
{HKQuantityType *distanceType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierDistanceWalkingRunning];NSSortDescriptor *timeSortDescriptor = [[NSSortDescriptor alloc] initWithKey:HKSampleSortIdentifierEndDate ascending:NO];HKSampleQuery *query = [[HKSampleQuery alloc] initWithSampleType:distanceType predicate:[HealthKitManage predicateForSamplesToday] limit:HKObjectQueryNoLimit sortDescriptors:@[timeSortDescriptor] resultsHandler:^(HKSampleQuery * _Nonnull query, NSArray<__kindof HKSample *> * _Nullable results, NSError * _Nullable error) {if(error){completion(0,error);}else{double totleSteps = 0;for(HKQuantitySample *quantitySample in results){HKQuantity *quantity = quantitySample.quantity;HKUnit *distanceUnit = [HKUnit meterUnitWithMetricPrefix:HKMetricPrefixKilo];double usersHeight = [quantity doubleValueForUnit:distanceUnit];totleSteps += usersHeight;}NSLog(@"当天行走距离 = %.2f",totleSteps);completion(totleSteps,error);}}];[self.healthStore executeQuery:query];
}
  • (7)、NSPredicate当天时间段的方法实现
/*!*  @brief  当天时间段**  @return 时间段*/
+ (NSPredicate *)predicateForSamplesToday {NSCalendar *calendar = [NSCalendar currentCalendar];NSDate *now = [NSDate date];NSDateComponents *components = [calendar components:NSCalendarUnitYear|NSCalendarUnitMonth|NSCalendarUnitDay fromDate:now];[components setHour:0];[components setMinute:0];[components setSecond: 0];NSDate *startDate = [calendar dateFromComponents:components];NSDate *endDate = [calendar dateByAddingUnit:NSCalendarUnitDay value:1 toDate:startDate options:0];NSPredicate *predicate = [HKQuery predicateForSamplesWithStartDate:startDate endDate:endDate options:HKQueryOptionNone];return predicate;
}

3、在控制器里展示出来读取的数据
(1)、首先导入头文件,并添加Label

#import "HealthKitManage.h"
@interface ViewController ()@end@implementation ViewController
{UILabel *stepLabel;UILabel *distanceLabel;
}

(2)创建界面,展示数据

- (void)viewDidLoad {[super viewDidLoad];// Do any additional setup after loading the view, typically from a nib.UIButton *btn1 = [UIButton buttonWithType:UIButtonTypeCustom];btn1.frame = CGRectMake(50, 100, 100, 40);[btn1 setTitle:@"计步" forState:UIControlStateNormal];btn1.backgroundColor = [UIColor cyanColor];[self.view addSubview:btn1];[btn1 addTarget:self action:@selector(onClickBtn1) forControlEvents:UIControlEventTouchUpInside];UIButton *btn2 = [UIButton buttonWithType:UIButtonTypeCustom];btn2.frame = CGRectMake(50, 160, 100, 40);[btn2 setTitle:@"距离" forState:UIControlStateNormal];btn2.backgroundColor = [UIColor cyanColor];[self.view addSubview:btn2];[btn2 addTarget:self action:@selector(onClickBtn2) forControlEvents:UIControlEventTouchUpInside];stepLabel = [[UILabel alloc] initWithFrame:CGRectMake(50, 220, 200, 40)];stepLabel.backgroundColor = [UIColor cyanColor];[self.view addSubview:stepLabel];distanceLabel = [[UILabel alloc] initWithFrame:CGRectMake(50, 280, 200, 40)];distanceLabel.backgroundColor = [UIColor cyanColor];[self.view addSubview:distanceLabel];
}- (void)onClickBtn1
{HealthKitManage *manage = [HealthKitManage shareInstance];[manage authorizeHealthKit:^(BOOL success, NSError *error) {if (success) {NSLog(@"success");[manage getStepCount:^(double value, NSError *error) {NSLog(@"1count-->%.0f", value);NSLog(@"1error-->%@", error.localizedDescription);dispatch_async(dispatch_get_main_queue(), ^{stepLabel.text = [NSString stringWithFormat:@"步数:%.0f步", value];});}];}else {NSLog(@"fail");}}];
}- (void)onClickBtn2
{HealthKitManage *manage = [HealthKitManage shareInstance];[manage authorizeHealthKit:^(BOOL success, NSError *error) {if (success) {NSLog(@"success");[manage getDistance:^(double value, NSError *error) {NSLog(@"2count-->%.2f", value);NSLog(@"2error-->%@", error.localizedDescription);dispatch_async(dispatch_get_main_queue(), ^{distanceLabel.text = [NSString stringWithFormat:@"公里数:%.2f公里", value];});}];}else {NSLog(@"fail");}}];
}

4、展示成果

这篇关于iOS开发-读取“健康”中的步数和步行+跑步距离的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/411010

相关文章

Android开发中gradle下载缓慢的问题级解决方法

《Android开发中gradle下载缓慢的问题级解决方法》本文介绍了解决Android开发中Gradle下载缓慢问题的几种方法,本文给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧... 目录一、网络环境优化二、Gradle版本与配置优化三、其他优化措施针对android开发中Gradle下载缓慢的问

使用Go语言开发一个命令行文件管理工具

《使用Go语言开发一个命令行文件管理工具》这篇文章主要为大家详细介绍了如何使用Go语言开发一款命令行文件管理工具,支持批量重命名,删除,创建,移动文件,需要的小伙伴可以了解下... 目录一、工具功能一览二、核心代码解析1. 主程序结构2. 批量重命名3. 批量删除4. 创建文件/目录5. 批量移动三、如何安

C#中读取XML文件的四种常用方法

《C#中读取XML文件的四种常用方法》Xml是Internet环境中跨平台的,依赖于内容的技术,是当前处理结构化文档信息的有力工具,下面我们就来看看C#中读取XML文件的方法都有哪些吧... 目录XML简介格式C#读取XML文件方法使用XmlDocument使用XmlTextReader/XmlTextWr

Android 悬浮窗开发示例((动态权限请求 | 前台服务和通知 | 悬浮窗创建 )

《Android悬浮窗开发示例((动态权限请求|前台服务和通知|悬浮窗创建)》本文介绍了Android悬浮窗的实现效果,包括动态权限请求、前台服务和通知的使用,悬浮窗权限需要动态申请并引导... 目录一、悬浮窗 动态权限请求1、动态请求权限2、悬浮窗权限说明3、检查动态权限4、申请动态权限5、权限设置完毕后

基于Python开发PPTX压缩工具

《基于Python开发PPTX压缩工具》在日常办公中,PPT文件往往因为图片过大而导致文件体积过大,不便于传输和存储,所以本文将使用Python开发一个PPTX压缩工具,需要的可以了解下... 目录引言全部代码环境准备代码结构代码实现运行结果引言在日常办公中,PPT文件往往因为图片过大而导致文件体积过大,

使用DeepSeek API 结合VSCode提升开发效率

《使用DeepSeekAPI结合VSCode提升开发效率》:本文主要介绍DeepSeekAPI与VisualStudioCode(VSCode)结合使用,以提升软件开发效率,具有一定的参考价值... 目录引言准备工作安装必要的 VSCode 扩展配置 DeepSeek API1. 创建 API 请求文件2.

基于Python开发电脑定时关机工具

《基于Python开发电脑定时关机工具》这篇文章主要为大家详细介绍了如何基于Python开发一个电脑定时关机工具,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1. 简介2. 运行效果3. 相关源码1. 简介这个程序就像一个“忠实的管家”,帮你按时关掉电脑,而且全程不需要你多做

Java中的Opencv简介与开发环境部署方法

《Java中的Opencv简介与开发环境部署方法》OpenCV是一个开源的计算机视觉和图像处理库,提供了丰富的图像处理算法和工具,它支持多种图像处理和计算机视觉算法,可以用于物体识别与跟踪、图像分割与... 目录1.Opencv简介Opencv的应用2.Java使用OpenCV进行图像操作opencv安装j

Java读取InfluxDB数据库的方法详解

《Java读取InfluxDB数据库的方法详解》本文介绍基于Java语言,读取InfluxDB数据库的方法,包括读取InfluxDB的所有数据库,以及指定数据库中的measurement、field、... 首先,创建一个Java项目,用于撰写代码。接下来,配置所需要的依赖;这里我们就选择可用于与Infl

C#读取本地网络配置信息全攻略分享

《C#读取本地网络配置信息全攻略分享》在当今数字化时代,网络已深度融入我们生活与工作的方方面面,对于软件开发而言,掌握本地计算机的网络配置信息显得尤为关键,而在C#编程的世界里,我们又该如何巧妙地读取... 目录一、引言二、C# 读取本地网络配置信息的基础准备2.1 引入关键命名空间2.2 理解核心类与方法