根据新闻报导,健康与健美在今时今日的重要程度比已往任何时候都高。说起来有点可笑,似乎就在几天之前,笔者就见到过类似的新闻。或许,这是当人逐渐变老之后挥之不去的感觉吧——渴望保持健康以及健美的感觉。不管怎么说,健康与健美是一个重要话题。技术的进步,尤其是移动应用与硬件世界的不断提高,正为这个似乎日益成长的话题带来全新的契机。
healthkit 是苹果公司推出的一款移动应用平台,旨在为重要、可追踪的健康数据与注重健康、热衷锻炼的科技消费者搭起桥梁。这很酷。用户可以轻松地追踪一段时间内可测量的健身与健康数据。除了了解自身的健康数据,看到图表中喜人的增长曲线也的确鼓舞人心。
作为开发者,我们需要征求许可才能从/向 healthkit 读取/写入数据。实际上,我们需要明确地声明打算读取或改变的数据。此外,任何使用 healthkit 的应用都必须包含隐私政策,这样一来,用户才能对其信息的处理感到更加放心。
在本文中,我们将打造一个有趣的小应用,它会从 healthkit 读取数据,也会向其写入新数据。来见一见 onehourwalker 吧。

onehourwalker 是一款追踪使用者在一个小时内行走或跑步之距离的健身应用。用户可以将距离与 healthkit 分享,之后就能在健康应用中读取之。我知道,一个小时听起来有点过于乐观了(至少笔者本人可能无法坚持下去)。因此,用户也可以提早中止计数,并分享距离。
额,到目前为止,似乎 onehourwalker 只会向 healthkit 写入数据。我们需要读取什么数据呢?
好问题!在步行锻炼时,我喜欢选择乡间或林间小路。常常,我会遇到树枝低垂的区域。而我是一条身高 193cm 的汉子,这真的让我很苦恼。解决办法是:从 healthkit 读取用户的身高数据,将之打印为应用的一个标签。这个标签可以作为对用户的善意提醒,这样,他们就能避免在步行时被树枝打到。
首先,在我们的应用中启用 healthkit。在项目导航中,点击 onehourwalker,之后点击 targets 下面的 onehourwalker,之后选择屏幕顶部的 capabilities 选项。
查看 capabilities 列表的底部,启用 <code>healthkit</code>。这一简单的操作会将 healthkit 权限添加到 app id,将 healthkit 键添加到 info plist 文件,将 healthkit 权限添加到授权文件,并且与 <code>healthkit.framework</code> 相连接。就是这么简单。
接下来,跳转到 <code>timerviewcontroller.swift</code>,开始将 healthkit 引入 onehourwalker。首先,创建一个 healthkitmanager 实例。
所有 healthkit 工作都会在 <code>healthkitmanager.swift</code> 中进行。它会包含重要的方法,我们很快就会谈到。
正如在前文介绍部分所述,我们需要取得用户的许可,才能读取并修改他们的健康数据。在 <code>viewdidload()</code>中,我们就得这么做。
<code>gethealthkitpermission()</code> 方法会调用 manager 的 <code>authorizehealthkit()</code>方法。如果一切顺利,我们便能调用<code>setheight()</code>方法。不过,我们很快会在后文中谈到此方法。
在 healthkitmanager.swift 中,我们会创建 authorizehealthkit() 方法。然而,除此之外,我们需要创建 healthkit 存储,用于连接应用与 healthkit 的数据。
在请求获取用户健康数据的授权时,我们需要明确指定打算读取以及修改的信息。对本例而言,我们需要读取用户的身高,从而帮助他们躲避有危险的低垂枝丫。我们希望 healthkit 能提供一个可以转化为可理解的身高的 hkobject 量。此外,我们还要获得修改 hkobject 量的许可,以记录用户的行走及跑步距离。
在处理好 onehourwalker 与 ipad 通信的可能性后,我们做出官方请求。
在 <code>healthkitmanager.swift</code> 中,创建从 healthkit 读取用户身高数据的 <code>getheight()</code> 方法。
查询身高数据的第一步是创建一个断言以定义时间参数。我们是在请求一段时间内的所有身高数据——与当前日期相距甚远的一个过去的日期。显然,这会返回一个数组。然而,我们只想要最近期的身高,因此,我们请求数据时可以让最新的数据排在数组的最前头。
在构建这一查询时,我们会把数组的长度限制为1。在考虑好出现错误的可能性后,我们会将结果中的首个也即唯一一个数组项目分配给 lastheight。接下来,完善 getheight() 方法。最后,针对用户的健康数据执行查询。
回到 <code>timerviewcontroller.swift</code>,在 app 真正投入使用之前,假设用户授权了适当的许可,则 <code>setheight()</code> 方法会被 <code>gethealthkitpermission()</code> 调用。
首先,我们需要为 hkquantitysample 实例声明一个身高变量。
在 <code>share()</code> 方法之上,我们会创建 <code>setheight()</code> 方法。我们请求的身高数据样本以 <code>hkquantity</code> 返回,标识符 <code>hkquantitytypeidentifierheight</code> 知道这一对象。
接下来,调用在 manager 中创建的 <code>getheight()</code> 方法。有了身高样本,我们还需要将之翻译为恰当的字符串以展示在标签中。与往常一样,考虑所有可能的错误情况是很重要的。
到此,用户就可以打开 app,查看他们的身高(如果他的健康应用中记录着身高数据),开启计时器,追踪他跑步或行走的距离了。接下来,我们要处理将距离数据写入健康应用的过程,这样,用户才能在同一个应用中保存其所有的健身数据。
在用户结束外出锻炼之后,不管有没有到60分钟,他可能会使用 share(分享)按钮将其辛苦赚得的运动距离发送到健康应用。所以,在 share() 方法中,我们需要调用 <code>healthkitmanager.swift</code> 的 <code>savedistance()</code> 方法来实现这一过程。在这个方法中,我们会发送运动距离以及取得该距离的日期。这样,用户便能在第二天争取更好的成绩。
接下来,回到 manager,我们要在此处创建 <code>savedistance()</code> 方法。首先,我们要让 healthkit 知道我们打算写入一个代表步行及跑步距离的量。之后,将度量单位设置为英里,并赋值官方的样本量。healthkit 的 <code>saveobject()</code> 方法会将此数据写入用户的健康数据。
跳转到健康应用,所记录的数据会出现在 walking + running distance(行走+跑步距离)一行(如果已经启用)。此外,依照下面的路径,我们可以看到详细的样本数据:health data tab(健康数据选项卡) > fitness(健身) > walking + running distance(行走+跑步距离) > show all data(显示所有数据)。我们的数据就在此列表中。轻击一个单元,我们的图标(目前还未设置)就会与距离一同出现。再次点击此单元,就能看到完整的细节数据。
借助 onehourwalker,我们便能为全世界 ios 用户的身体健康贡献一份力量。然而,这只是一个开始。在使用 healthkit 读取并修改健康数据的道路上,还有非常多的可能性。
当然,对用户而言,拥有这些可追踪数据的好处很多。人们可以轻松地按照日期、星期进行比较,从而激励自己朝着目标努力。不过,真正的伟大之处在于,开发者可以提供全新的,富有创造力的有趣方法来获取数据。