HealthKit 健康

1、HealthKit 框架

1.1 HealthKit 简介

  • HealthKit 是 Apple 公司在推出 iOS 8 系统时一块推出的关于健康信息的框架。如果 iPhone 手机系统升级到 iOS8 之后就会发现多了一个健康 App,这就是 Apple 提供的一个记录用户健康信息的 App,可以用它来分享健康和健身数据。HealthKit 管理从不同来源获得的数据,并根据用户的偏好设置,自动将不同来源的所有数据合并起来。应用还可以获取每个来源的原始数据,然后执行自己的数据合并。还可以指定数据的来源,比如我们自己创建一个 App,在我们的 App 中使用了 HealthKit 框架之后只要经过用户的认证,就可以在我们的 App 之中给健康分享数据或者从健康中获取数据。

  • HealthKit 也可以直接与健康和健身设备一起工作,在 iOS8.0+ 中,系统可以自动将兼容的低功耗蓝牙心率仪的数据直接保存在 HealthKit 存储中。如果有 M7 运动协处理器,系统还可以自动导入计步数据。其他的设备和数据源必须要有配套的应用才可以获取数据并保存在 HealthKit 中。但是其他信息或者设备需要配套的应用才能获取到数据并导入到 HealthKit 中并在健康中显示。

  • HealthKit 另外提供了一个应用来帮助管理用户的健康数据。健康应用为用户展示 HealthKit 的数据。用户可以使用健康应用来查看、添加、删除或者管理其全部的健康和健身数据。用户还可以编辑每种数据类型的分享权限。

  • HealthKit 和健康应用在 iPad 上都不可用。HealthKit 框架不能用于应用扩展。

1.2 HealthKit 用户数据安全及隐私

  • 由于健康数据可能是敏感的,HealthKit 通过精确控制哪些信息允许应用读取,从而让用户可以控制这些数据。用户必须明确设置每个应用在 HealthKit 存储中读写的权限。用户可以单独为每种数据类型设置准许或拒绝的权限。例如,用户可以允许你的应用读取计步数据,但是不允许读取血糖水平。为了防止可能的信息泄露,应用是不知道它是否被禁止读取数据的。从应用的角度来看,如果被禁止读取数据,就是没有那种类型的数据存在。

  • HealthKit 的数据不会保存在 iCloud 中,也不会在多设备间同步。这些数据只会保存在用户的本地设备中。为了安全考虑,当设备没有解锁时,HealthKit 存储的数据是加密的。

  • 另外,你的应用如果主要不是提供健康或健身服务的话,那就不能调用 HealthKit 的 API。如果你的应用提供健康和健身服务,就必须要在销售文本和用户界面上明确的表明。特别是下面几条指导适用于所有 HealthKit 应用。

    • 1、你的应用不应该将 HealthKit 收集的数据用于广告或类似的服务。注意,可能在使用 HealthKit 框架应用中还是要服务广告,但是你不能使用 HealthKit 中的数据来服务广告。

    • 2、在没有用户的明确允许下,你不能向第三方展示任何 HealthKit 收集的数据。即使用户允许,你也只能向提供健康或健身服务的第三方展示这些数据。

    • 3、你不能将 HealthKit 收集的数据出售给广告平台、数据代理人或者信息经销商。

    • 4、如果用户允许,你可以将 HealthKit 数据共享给第三方用于医学研究。

    • 5、你必须明确说明,你和你的应用会怎样使用用户的 HealthKit 数据。

  • 你必须为每个使用 HealthKit 框架的应用提供一份隐私策略。你可以在以下网站找到创建隐私策略的指导:

    • 1、Personal Health Record model (for non-HIPAA apps)

    • 2、HIPAA model (for HIPAA covered apps)

    • 这些模板由 ONC 开发,通过直白的语言和平易近人的设计来解释用户数据是如何被收集和共享的,从而提高用户的体验和理解。这些不是用来替代基本的互联网隐私策略,而且开发者应该咨询 ONC 来了解你的应用适用哪种模板。这些模板仅供参考,Apple 不承担你使用这些模板带来的后果。

  • 注意:

    • 这一节提供了一些指导来帮助你创建一个 HealthKit 应用,并尊重用户的隐私。了解 Apple 对使用 HealthKit 和用户健康相关数据的要求是很有必要的。参看 App Store Review Guidelines 中的 HealthKit 章节来了解更多,可以在 Apple 的 App Review Support 页面中找到。

    • 关于使用敏感用户数据的更多技术信息,参见 App Programming Guide for iOS 中的 Best Practices for Maintaining User Privacy

1.3 从接入 HealthKit 中获益

  • 健康和健身应用可以从接入 HealthKit 中获益颇多。下面列出了一些主要的好处。

  • 分离数据收集、数据处理和社交化。现代的健康和健身体验设计许多不同的方面,例如收集和分析数据,为用户提供可操作的信息和有用的可视化信息,以及允许用户参与到社区讨论中。现在由HealthKit负责实现这些方面,而你可以专注于实现你最感兴趣的方面,把其他的任务交给更专业的应用。

  • 这些责任的分离也可以让用户受益。每个用户都可以随意选择最喜爱的体重追踪应用、计步应用和健康挑战应用。这意味着用户可以选择一套应用,每个应用都能很好的满足用户的某个需求。但是由于这些应用可以自由地交换数据,所以这一整套应用比单个应用能提供更好的体验。

  • 例如,一些朋友决定参加一个日常的计步挑战。每个人都可以使用他偏爱的硬件设备或应用来追踪计步数据,但是他们都还可以使用相同的社交应用来挑战。

  • 减少应用间分享的障碍。HealthKit 使应用间共享数据变得更容易。对于开发者来说,你不在需要下载 API 并编写代码来和其他应用共享。当有新的 HealthKit 应用时,它们就通过 HealthKit 自动开始共享数据了。

  • 由于不需要手动设置应用关联或者导入导出他们的数据,这对用户来说很好。用户仍然需要设置哪些应用可以读写 HealthKit 中的数据,还有每个应用可以读取到哪些数据。一旦用户允许访问,应用就可以自由无阻地读取数据了。

  • 提供更丰富的数据和更有意义的内容。应用可以读取到范围更广的数据,从而可以得到一个完整的关于用户健康和健身需求。在许多情况下,应用可以基于 HealthKit 中的额外信息修改它的计量单位或者提示。例如,训练应用不仅可以根据用户已经消耗的热量,还可以参考他今天已经吃的食物种类和数量,来给出一个训练后吃什么的建议。

  • 让应用参与到一个更大的生态系统中。应用通过共享它使用 HealthKit 收集的数据来获益。成为这个大生态系统的一部分能帮助提高你的应用的曝光度和实用性。更重要的是,接入 HealthKit 能让你的应用和用户已经拥有喜爱的应用一起工作。如果你的应用不能和其他已经在使用的应用共享数据,那么用户很可能就去寻找别的应用了。

1.4 HealthKit 设计思路

  • HealthKit 在各个应用之间提供了一种有意义的方式共享数据。为了达到这点,框架限制只能使用预先定义好的数据类型和单位。这些限制保证了其他应用能理解这些数据是什么意思以及怎样使用。因此,开发者不能创建自定义数据类型和单位。而 HealthKit 尽量会提供一个应该完整的数据类型和单位。

  • 框架还大量使用了子类化,在相似的类间创建层级关系。通常这些类间都有一些细微但是重要的差别。还有不少很相关的类,需要正确地区别开才能一起工作。例如 HKObjectHKObjectType 抽象类有很多平行层级的子类。当使用 object 和 object type 时,必须确保使用匹配的子类。

  • 1、HealthKit 中所有的对象都是 HKObject 的子类。大部分 HKObject 对象子类都是不可变的,每个对象都有下面的属性

    • UUID:每个对象的唯一标识符。

    • Source:数据的来源,来源可以是直接把数据存进 HealthKit 的设备,或者是应用。当一个对象保存进 HealthKit 中时,HealthKit 会自动设置其来源。只有从 HealthKit 中获取的数据 source 属性才可用。

    • Metadata:一个包含关于该对象额外信息的字典。元数据包含预定义和自定义的键。预定义的键用来帮助在应用间共享数据。自定义的键用来扩展 HealthKit 对象类型,为对象添加针对应用的数据。

  • 2、HealthKit 的对象主要分为特征和样本

    • 特征对象代表一些基本不变的数据。包括用户的生日、血型和生理性别。我们创建的应用不能保存特征数据。用户必须通过健康应用来输入或者修改这些数据。

    • 样本对象代表某个特定时间的数据,所有的样本类型的对象都是 HKSample 的子类。它们都有下面的特性:

      • Type:样本类型,例如:睡眠分析样本、步行距离样本、心率样本等。
      • StartDate:样本开始时间。
      • EndDate:样本结束时间。如果样本代表时间中的某一刻,结束时间和开始时间相同。如果样本代表一段时间内收集的数据,结束时间应该晚于开始时间。
    • 样本类型又可以分为四个类型:

      • 类别样本(HKCategorySample):这种样本代表一些可以被分为有限种类的数据。在 iOS8.0 中,只有一种类别样本,睡眠分析。更多信息: HKCategorySample Class Reference

      • 数量样本(HKQuantitySample):这种样本代表一些可以存储为数值的数据。数量样本是 HealthKit 中最常见的数据类型。这些包括用户的身高和体重,还有一些其他数据,例如行走的步数,用户的体温和脉搏率。更多信息: HKQuantitySample Class Reference

      • 关系样本(HKCorrelation):这种样本代表复合数据,包含一个或多个样本。在 iOS8.0 中,HealthKit 使用 correlation 来代表食物和血压。在创建食物或者血压数据时,你应该使用 correlation。更多信息: HKCorrelation Class Reference

      • 训练活动(HKWorkout):代表某些物理活动,像跑步、游泳,甚至游戏。Workout 通常有类型、时长、距离、和消耗能量这些属性。你还可以为一个 workout 关联许多详细的样本。不像 correlation,这些样本是不包含在 workout 里的。但是,它们可以通过 workout 获取到。更多信息: HKWorkout Class Reference

2、HealthKit 使用方法

2.1 设置 HealthKit

  • 在你开始使用 HealthKit 之前,必须要执行下列步骤:

    • 1、在 Xcode 中打开 HealthKit 功能。

    • 2、调用 isHealthDataAvailable 方法来查看 HealthKit 在该设备上是否可用。HealthKit 在 iPad 上不可用。

    • 3、为你的应用实例化一个 HKHealthStore 对象。每个应用只需要一个 HealthKit 存储实例。这个存储实例就是你和 HealthKit 数据库交互的主要接口。

    • 4、使用 requestAuthorizationToShareTypes:readTypes:completion: 方法来请求获取 HealthKit 数据的权限。对每种类型的数据,你都必须请求许可来共享和读取。

  • 如果用户允许分享某种类型的数据,那么你可以创建这种类型的新样本,并保存在 HealthKit 中。你应该使用 authorizationStatusForType: 来检查是否允许分享这种类型的数据。

  • 如果用户允许读取某种类型的数据,那么你就可以从 HealthKit 中读取这些数据。不幸的是,即使知道用户拒绝读取某种类型的数据,也可能会显示出潜在的健康问题。因此,你的应用无法确定用户是否允许读取数据。如果你没有得到读取某种数据的许可,那简单来看就好像是 HealthKit 中没有这种类型的数据。

  • 关于设置 HealthKit 的更多内容,参见 HKHealthStore Class Reference

  • 有一个展示了如何设置和使用 HealthKit 的例子,参见 Fit: Store and Retrieve HealthKit Data

2.2 向 HealthKit 存储中添加样本

  • 你的应用可以创建新的样本,并添加到HealthKit存储中。对所有样本类型来说,大致的过程都是类似的,但是又有一些不同。

  • 每个 HKSample 子类都有自己的便捷方法来实例化样本对象。

  • 对于数量样本,你必须创建一个 HKQuantity 类的实例。数量的单位必须和类型标识符文档中描述的可用单位相关。例如,HKQuantityTypeIdentifierHeight文档中说明它使用长度单位,因此,你的数量必须使用厘米、米、英尺、英寸或者其他长度单位。更多信息,参见 HKQuantitySample Class Reference

  • 对于类别样本,它的值必须和类型标识符文档中描述的枚举值相关。例如,HKCategoryTypeIdentifierSleepAnalysis 文档中说明它使用 HKCategoryValueSleepAnalysis 枚举值。因此你在创建样本时必须从这个枚举中传递一个值。更多信息,参见 HKCategorySample Class Reference

  • 对于 correlation,你必须先创建 correlation 包含的所有样本。correlation 的类型标识符描述了它可以包含的类型和对象的数量。不要把被包含的对象存进 HealthKit。它们是以 correlation 的一部分存储的。更多信息,参见 HKCorrelation Class Reference

  • workout 和其他类型的样本有些不同。首先,创建 HKWorkoutType 实例并不需要指定类型标识符。所有的 workout 都是用同样的类型标识符。第二,对于每个 workout 你都需要提供一个 HKWorkoutActivityType 值。这个值定义了 workout 中执行的活动的类型。最后,当 workout 保存到 HealthKit 后,你可以给 workout 关联额外的样本。这些样本提供了 workout 的详细信息。更多信息,参见 HKWorkout Class Reference

2.3 读取 HealthKit 数据

  • HealthKit 提供了许多查询读取数据的方法。

    • 1、直接方法查询。HealthKit 提供了直接读取特征数据的方法。这些方法只能用于读取特征数据。更多信息:HKHealthStore Class Reference

    • 2、样本查询。这是使用最多的查询。使用样本查询来读取任何类型的样本数据。当你想要对结果进行排序或者限制返回的样本总数时,样本查询就特别有用。更多信息:HKSampleQuery Class Reference

    • 3、观察者查询。这是一个长时间运行的查询,它会检测 HealthKit 存储,并在匹配到的样本发生变化时通知你。如果当存储发生变化时你想得到通知,就使用观察者查询。你可以让这些查询在后台执行。更多信息:HKObserverQuery Class Reference

    • 4、锚定对象查询。用这种查询来搜索添加进存储的项。当锚定查询第一次执行时,会返回存储中所有匹配的样本。在接下来的执行中,只会返回上一次执行之后添加的项目。通常,锚定对象查询会和观察者查询一起使用。观察者查询告诉你某些项目发生了变化,而锚定对象查询来决定有哪些(如果有的话)项目被添加进了存储。更多信息:HKAnchoredObjectQuery Class Reference

    • 5、统计查询。使用这种查询来在一系列匹配的样本中执行统计运算。你可以使用统计查询来计算样本的总和、最小值、最大值或平均值。更多信息:HKStatisticsQuery Class Reference

    • 6、统计集合查询。使用这种查询来在一系列长度固定的时间间隔中执行多次统计查询。通常使用这种查询来生成图表。查询提供了一些简单的方法来计算某些值,例如,每天消耗的总热量或者每5分钟行走的步数。统计集合查询是长时间运行的。查询可以返回当前的统计集合,也可以监测HealthKit存储,并对更新做出响应。更多信息:HKStatisticsCollectionQuery Class Reference

    • 7、Correlation 查询。使用这种查询来在 correlation 查找数据。这种查询可以为 correlation 中每个样本类型包含独立的谓词。如果你只是想匹配 correlation 类型,那么请使用样本查询。更多信息:HKCorrelation Class Reference

    • 8、来源查询。使用这种查询来查找 HealthKit 存储中的匹配数据的来源(应用和设备)。来源查询会列出储存的特定样本类型的所有来源。更多信息:HKSourceQuery Class Reference

2.4 单位换算

  • HealthKit 使用 HKUnitHKQuantity 类来支持单位。HKUnit 提供了单一单位的表示。它支持大部分的公制和英制单位,当然还包括基本单位和符合单位。基本单位代表单一的度量,例如米、磅或者秒。复合单位使用数学运算连接一个或多个基本单位,例如 m/s 或者 lb/ft2。

  • HKUnit 提供了便捷方法来创建 HealthKit 支持的所有基本单位。它还提供了构建复合单位需要的数学运算。最后,你还可以通过直接使用恰当的格式化的单位字符串来创建复合单位。更多信息,参见 HKUnit Class Reference

  • HKQuantity 类存储了给定单位的值。之后你可以用任何兼容的单位来取值。这样,你的应用就可以很轻松的完成单位换算。更多信息,参见 HKQuantity Class Reference

  • 在某些场合,你可以使用格式化器来本地化数量。iOS8 提供了提供了新的格式化器来处理长度(NSLengthFormatter)、质量(NSMassFormatter)和能量(NSEnergyFormatter)。对于其他的数量,你需要自己来换算单位和本地化数据。

2.5 HKHeathStore 数据库

  • HealthKit 的核心就是它,它代表 HealthKit 的数据库,使用它就可以从数据库中读取数据。比较重要的方法:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    // 判断当前设置是否支持 HealthKit
    + (BOOL)isHealthDataAvailable;

    // 向用户请求同意读写某些数据
    - (void)requestAuthorizationToShareTypes:(nullable NSSet<HKSampleType *> *)typesToShare
    readTypes:(nullable NSSet<HKObjectType *> *)typesToRead
    completion:(void (^)(BOOL success, NSError * _Nullable error))completion;

    // 向数据库中添加数据
    - (void)saveObject:(HKObject *)object
    withCompletion:(void(^)(BOOL success, NSError * _Nullable error))completion;

    // 执行查询,即上面介绍的几种查询方法
    - (void)executeQuery:(HKQuery *)query;

2.6 多线程

  • HealthKit 存储是线程安全的,大部分 HealthKit 对象是不可变的。通常来说,你可以在多线程环境中安全地使用 HealthKit。

  • 注意:

    • 所有 HealthKit API 的完成回调都在一个私有的后台队列中执行。所以在你更新用户界面或者修改一些只能在主线程中处理的资源之前,你应该把这些数据传回主线程。
  • 关于多线程和并发编程的更多信息,参见 Concurrency Programming Guide

2.7 添加数字签名

  • HealthKit 中的数字签名元数据对象提供了由可信设备生成的样本记录的数据完整性。元数据项存储了一份数字签名过的样本记录副本。签名是由设备生成的(由于设备存储了私有签名密钥,所以设备应该是防篡改的)。这样数据的使用者就可以通过设备的公钥来检查签名,进而验证记录数据是否被修改过。由于每条记录都是独立签名的,所以每条记录总共能存储大约 1K bytes 的签名。因此,这种元数据签名项是给那些样本率最多在每天几次的记录使用的。更高的样本率需要对样本组进行签名,这已经超出了本文档的范围。

  • 通常,私钥是在制造时置入防篡改的测量设备中的。(私钥重置或证书更新的政策或机制不在本文档的范围内)相关的公钥会由设备制造商公布,例如在它们的网站上。设备应该将每个样本的样本数据和签名传给 iOS 应用,这两者都会储存在 HealthKit 数据库中。注意,数字签名的公私钥是用来提供数据完整性检查的,不是用来加密的。数据记录中的实际值都是明文。

  • 数字签名的格式是 IETF RFC 5652 中的 CMS(Cryptographic Message Syntax)。签名使用 ASN.1 的 DER(Distinguished Encoding Rules)编码。使用的信息摘要应该是 SHA256,签名加密应该是 FIPS PUB 186-4 Digital Signature Standard Elliptic Curve P-256。这样长度和效率都有保证。另外,整个签名都应该使用 bsae64 编码,这样就能存储在 HealthKit NSString 元数据对象中。

  • 签名应该是 ASN.1 Signed-data Content Type:

    1
    SignedData ::= SEQUENCE {version CMSVersion, digestAlgorithms DigestAlgorithmIdentifiers, encapContentInfo EncasulatedContentInfo, signerInfos SignerInfo }
  • SignerInfo Type 是:

    1
    SignerInfo ::= SEQUENCE {version CMSVersion, sid SignerIdentifier, digestAlgorithm DigestAlgorithmIdentifier, signatureAlgorithem SignatureAlgorithmIdentifier, signatureSignatureValue }
  • 上面就是摘要和签名的算法。可选项目都没有包含在其中。SignerIdentifier 用来取得适当的公钥,来对签名进行验证。

  • EncapsulatedContentInfo 是从由设备生成的样本记录中的相关项目的副本。副本应该用 ASN.1 DER 编码,并应至少包含一个样本时间戳和采样值。将记录数据拷贝进签名内,是为了有一个稳定的定义良好的二进制编码(ASN.1 DER),这对于生成一个可验证的签名来说是必要的。ASN.1 编码的 plist 结构(键值对),应该能满足大部分记录类型。(参见“使用 ASN.1 DER 来编码 plist 结构”)

3、HealthKit 的使用

  • 1、添加 HealthKit

    • 在项目的 TARGETS -> Capabilities 中打开 HealthKit 开关。

    • 打开开关之后,左侧会自动导入框架

  • 2、设置 HealthKit 隐私权限

    • 在项目的 Info.plist 文件中添加以下相应的隐私设置。

      1
      2
      3
      4
      5
      // 读取数据权限
      Privacy - Health Share Usage Description

      // 写入数据权限
      Privacy - Health Update Usage Description
  • 3、添加头文件

    • 在需要使用的文件中添加以下头文件

      1
      2
      // 添加头文件
      #import <HealthKit/HealthKit.h>

3.1 获取特征信息

  • 对于请求特征信息,前提上用户通过健康添加了出生日期、性别、血型等特征信息。

3.2 获取步数

  • 首先声明一个 HKHealthStore 类的实例,去获取在健康里面获取数据的权限,在 iPad 上面是不支持此框架的,所以我们要进行一个判断。

    1
    2
    3
    4
    5
    // 判断设备是否支持 HealthKit,在 iPad 上面是不支持此框架的
    if (![HKHealthStore isHealthDataAvailable]) {
    NSLog(@"该设备不支持 HealthKit");
    return;
    }
  • 如果不是 iPad 正式开始获取权限。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    // 创建 healthStore 对象
    self.healthStore = [[HKHealthStore alloc] init];

    // 设置需要获取的权限,这里仅设置了步数
    HKObjectType *stepType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount];
    NSSet *healthSet = [NSSet setWithObjects:stepType, nil];

    // 从健康应用中获取权限
    [self.healthStore requestAuthorizationToShareTypes:nil
    readTypes:healthSet
    completion:^(BOOL success, NSError * _Nullable error) {

    if (success) {

    // 获取步数后我们调用获取步数的方法
    [self readStepCount];

    } else {
    NSLog(@"获取步数权限失败");
    }
    }];
  • 接下来需要实现获取步数的方法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    // 查询采样信息
    HKSampleType *sampleType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount];

    // NSSortDescriptor 来告诉 healthStore 怎么样将结果排序
    NSSortDescriptor *start = [NSSortDescriptor sortDescriptorWithKey:HKSampleSortIdentifierStartDate ascending:NO];
    NSSortDescriptor *end = [NSSortDescriptor sortDescriptorWithKey:HKSampleSortIdentifierEndDate ascending:NO];

    // 获取当前时间进行对比
    NSDate *now = [NSDate date];
    NSCalendar *calendar = [NSCalendar currentCalendar];
    NSUInteger unitFlags = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay |
    NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond;
    NSDateComponents *dateComponent = [calendar components:unitFlags fromDate:now];
    int hour = (int)[dateComponent hour];
    int minute = (int)[dateComponent minute];
    int second = (int)[dateComponent second];

    // 时间结果与想象中不同是因为它显示的是 0 区
    NSDate *nowDay = [NSDate dateWithTimeIntervalSinceNow:- (hour * 3600 + minute * 60 + second)];
    NSLog(@"今天 %@", nowDay);

    NSDate *nextDay = [NSDate dateWithTimeIntervalSinceNow:- (hour * 3600 + minute * 60 + second) + 86400];
    NSLog(@"明天 %@", nextDay);

    NSPredicate *predicate = [HKQuery predicateForSamplesWithStartDate:nowDay
    endDate:nextDay
    options:(HKQueryOptionNone)];

    // 查询的基类是 HKQuery,这是一个抽象类,能够实现每一种查询目标。
    // 这里我们需要查询的步数是一个 HKSample 类所以对应的查询类是 HKSampleQuery。
    // 下面的 limit 参数传 1 表示查询最近一条数据,查询多条数据只要设置 limit 的参数值就可以了,传入 0 表示查询所有数据。
    HKSampleQuery *sampleQuery = [[HKSampleQuery alloc]
    initWithSampleType:sampleType
    predicate:predicate
    limit:HKObjectQueryNoLimit
    sortDescriptors:@[start, end]
    resultsHandler:^(HKSampleQuery * _Nonnull query,
    NSArray<__kindof HKSample *> * _Nullable results,
    NSError * _Nullable error) {

    // 设置一个 int 型变量来作为步数统计
    int allStepCount = 0;

    for (int i = 0; i < results.count; i ++) {

    // 把结果转换为字符串类型
    HKQuantitySample *result = results[i];
    HKQuantity *quantity = result.quantity;
    NSMutableString *stepCount = (NSMutableString *)quantity;
    NSString *stepStr = [NSString stringWithFormat:@"%@", stepCount];

    // 获取 51 count 此类字符串前面的数字
    NSString *str = [stepStr componentsSeparatedByString:@" "][0];
    int stepNum = [str intValue];
    NSLog(@"stepNum: %d", stepNum);

    // 把一天中所有时间段中的步数加到一起
    allStepCount += stepNum;
    }
    NSLog(@"今天的总步数: %d", allStepCount);
    }];

    // 开始执行查询
    [self.healthStore executeQuery:sampleQuery];
文章目录
  1. 1. 1、HealthKit 框架
    1. 1.1. 1.1 HealthKit 简介
    2. 1.2. 1.2 HealthKit 用户数据安全及隐私
    3. 1.3. 1.3 从接入 HealthKit 中获益
    4. 1.4. 1.4 HealthKit 设计思路
  2. 2. 2、HealthKit 使用方法
    1. 2.1. 2.1 设置 HealthKit
    2. 2.2. 2.2 向 HealthKit 存储中添加样本
    3. 2.3. 2.3 读取 HealthKit 数据
    4. 2.4. 2.4 单位换算
    5. 2.5. 2.5 HKHeathStore 数据库
    6. 2.6. 2.6 多线程
    7. 2.7. 2.7 添加数字签名
  3. 3. 3、HealthKit 的使用
    1. 3.1. 3.1 获取特征信息
    2. 3.2. 3.2 获取步数
隐藏目录