如今,睡眠革命逐渐成为一种时尚,跟之前相比,人们不仅想知道自己的睡眠时间,同时对用于分析他们一定时间段内睡眠状态的数据感兴趣。包括硬件技术在内的,尤其是手机技能的提升,为用户这一日益增长的需求带来了全新的希望.
苹果提供了一种安全、炫酷的方式来显示用户的个人健康信息,并将这些信息安全的存储在 Health 这个内置的应用中。你不仅可以使用 HealthKit 来 创建一个健身应用 ,该框架还允许你访问睡眠的详细数据。这本次教程中,我将会给大家简要的介绍 HealthKit 这个框架,并演示如何创建一个简单的睡眠分析的应用。
**简介 **
HealthKit 提供了一个名为 HealthKit store 的结构用来存储加密的数据。你可以使用HKHealthStore
这个类来访问这个数据库。iPhone 和 Apple Watch 都有自己的 HealthKit store,他们之间的健康数据是同步。需要注意的是,在 Apple Watch 上老的数据会被定期的清除以节省空间。并且 ,iPad不支持HealthKit 和 Health 。
如果你想基于健康数据创建一个 iOS 或者 watchOS 应用,HealthKit 是一个非常强大的工具。它被设计的目的就是管理广泛地数据源,并且根据用户的偏好自动地合并不同来源的数据。应用程序还可以访问每一条原始数据,并且合并他们。这些数据不仅能够用于身体评估,健康状况评估以及营养状况评估,还能够用于分析睡眠质量。
接下来,我将会向你展示在 iOS 上如何利用 HealthKit 保存和访问睡眠数据。这种方法也同样适合 watchOS 上的应用。请注意本次教程使用的是 Swift 2.0 和 Xcode 7。因此,请确保你跟随此教程的时候使用的是 Xcode 7(或者以上)。
在此之前,下载最开始的工程 并解压。我已经为你创建了基本功能的用户界面。当你运行这个工程的时候,你将会看到一个定时器的 UI ,当你按下开始按钮以后就会显示计时。
** 使用 HealthKit**
我们使用这个应用的目的是使用开始和停止按钮来保存睡眠分析信息和复取数据。要使用 HealthKit,你必须给你的应用授权。也就是在你的应用中,按着 target -> capabilities -> 打开HealthKit开关
这个步骤
接下来,你需要用下面的代码在 ViewController
类中创建一个 HKHealthStore
的实例:
let healthStore = HKHealthStore()
随后我们将使用 HKHealthStore
这个实例来访问 HealthKit store。
如之前所说, HealthKit 授予用户权限来访问他们的健康数据。所以你在获得用户的睡眠分析数据权限(读/写)之前,你必须现请求用户的许可。要做到这一点,首先要导入内置的 HealthKit
框架,然后更新 viewDidLoad
里面的方法,如下:
override func viewDidLoad() {
super.viewDidLoad()
let typestoRead = Set([
HKObjectType.categoryTypeForIdentifier(HKCategoryTypeIdentifierSleepAnalysis)!
])
let typestoShare = Set([
HKObjectType.categoryTypeForIdentifier(HKCategoryTypeIdentifierSleepAnalysis)!
])
self.healthStore.requestAuthorizationToShareTypes(typestoShare, readTypes: typestoRead) { (success, error) -> Void in
if success == false {
NSLog(" Display not allowed")
}
}
}
这段代码将提示用户允许或拒绝请求的访问的权限。在闭包中,你可以对成功或者失败进行处理,并得到最终结果。用户没有必要授予你的应用所有你请求的权限。所以在你的应用中你必须妥善的处理这些错误。
但是出于测试的目的,你必须选择“允许”选项来授权你的应用能访问你设备上的健康数据。
写入睡眠分析数据
首先,我们如何复取睡眠分析数据呢?根据苹果文档,每个睡眠分析样品只能有一个值。为了区分用户是在床上还是睡着了,HealthKit 用了两个或者两个以上的重叠时间的样本。通过比较这些样品的开始和结束时间,应用就可以计算出一些次要的统计数据:
用户进入睡眠所花费的时间
用户在床上的时间和实际睡眠时间的百分比
用户在床上醒来的次数
用户在床上和睡着的时间的总和
简单地说,你按照下面的方法来保存你的睡眠分析数据到 HealthKit 商店:
1、我们需要定义两个
NSDate
的对象用于开始时间和结束时间。2、用
HKCategoryTypeIdentifierSleepAnalysis
创建一个HKObjectType
的实例。3、我们需要创建一个新的
HKCategorySample
类型的对象,你通常使用一类的样本来记录睡眠时间,单个的样本代表用户在床上或者在睡觉的时间段。因此,我们将会创建一个在床上和一个睡着了的重叠时间样本。4、最后,我们用
HKHealthStore
的saveObject
方法来保存上述实例。
如果你想用 Swift
实现上述所有,这里有保存在床上和睡眠中睡眠分析数据的代码片段。请把这些代码插入在ViewController
类中:
func saveSleepAnalysis() {
// alarmTime and endTime are NSDate objects
if let sleepType = HKObjectType.categoryTypeForIdentifier(HKCategoryTypeIdentifierSleepAnalysis) {
// we create our new object we want to push in Health app
let object = HKCategorySample(type:sleepType, value: HKCategoryValueSleepAnalysis.InBed.rawValue, startDate: self.alarmTime, endDate: self.endTime)
// at the end, we save it
healthStore.saveObject(object, withCompletion: { (success, error) -> Void in
if error != nil {
// something happened
return
}
if success {
print("My new data was saved in HealthKit")
} else {
// something happened again
}
})
let object2 = HKCategorySample(type:sleepType, value: HKCategoryValueSleepAnalysis.Asleep.rawValue, startDate: self.alarmTime, endDate: self.endTime)
healthStore.saveObject(object2, withCompletion: { (success, error) -> Void in
if error != nil {
// something happened
return
}
if success {
print("My new data (2) was saved in HealthKit")
} else {
// something happened again
}
})
}
}
当我们想把睡眠分析数据保存到 HealthKit 的时候上述方法将会被调用。
** 读取睡眠分析数据**
要读取睡眠分析数据,我们需要创建一个query
。首先你需要用 HKCategoryTypeIdentifierSleepAnalysis
定义一个 HKObjectType
类型的实例,你可能还需要一个谓词来筛选你用开始时间和结束时间复取的数据,也就是你想要检索的时间范围内的 NSDate 类型的对象。你还需要创建一个 sortDescriptor
排序的检索词来筛选出你想要的结果。
你的检索睡眠分析数据的代码应改像下面这样:
func retrieveSleepAnalysis() {
// first, we define the object type we want
if let sleepType = HKObjectType.categoryTypeForIdentifier(HKCategoryTypeIdentifierSleepAnalysis) {
// Use a sortDescriptor to get the recent data first
let sortDescriptor = NSSortDescriptor(key: HKSampleSortIdentifierEndDate, ascending: false)
// we create our query with a block completion to execute
let query = HKSampleQuery(sampleType: sleepType, predicate: nil, limit: 30, sortDescriptors: [sortDescriptor]) { (query, tmpResult, error) -> Void in
if error != nil {
// something happened
return
}
if let result = tmpResult {
// do something with my data
for item in result {
if let sample = item as? HKCategorySample {
let value = (sample.value == HKCategoryValueSleepAnalysis.InBed.rawValue) ? "InBed" : "Asleep"
print("Healthkit sleep: \(sample.startDate) \(sample.endDate) - value: \(value)")
}
}
}
}
// finally, we execute our query
healthStore.executeQuery(query)
}
}
这段代码查询了在 HealthKit 上的所有睡眠分析数据并按降序排列。然后每天结果上都带着是在床上的开始结束时间或者在睡觉的开始结束时间被打印出来。我已经设置了上限30用来检索最后记录的30个样本。你也可以用谓词的方法来选择你的自定义开始时间和结束时间。
应用测试
对于这个 demo,我已经使用 NSTimer 来显示你按下按钮之后经过的时间。当开始和结束按钮按下的时候将会创建 NSDate 的对象来保存所经过的时间作为睡眠分析数据。在停止的方法中,你可以调用 saveSleepAnalysis()
和 retrieveSleepAnalysis
方法来保存和获得睡眠数据。
@IBAction func stop(sender: AnyObject) {
endTime = NSDate()
saveSleepAnalysis()
retrieveSleepAnalysis()
timer.invalidate()
}
在你的应用程序中,你也许想要改变 NSDate 对象来选择相关的开始和结束时间(可能不同)来保存在床上和睡眠的的值。
一旦你做了这些改变,你可以运行这个 demo 然后开始计时。让它运行几分钟,然后点击停止按钮。然后,打开 Health 这个应用,你就可以找到你的睡眠数据。
一些关于 HealthKit 应用的建议
HealthKit 旨在提供一个公共平台,使应用程序开发人员能够很容易地共享和访问用户的数据,并避免任何可能的重复或不一致的数据。苹果审核指南对使用 HealthKit 有很明确的要求,如果对用户的读/写权限请求没有明确的描述就很可能导致应用程序被拒绝。
应用如果保存伪造或者错误的数据到健康应用的话也将被拒绝。这就意味着,你不能像在本次教程中睡眠分析这样天真的以你的算法计算不同的健康值。你应该尝试使用内置的传感器数据读取和操作一些参数,以避免计算错误。
关于完整的 Xcode 项目,你可以在 这里 看到。