今天,睡眠的变革是一种时尚,用户比以往任何时候都好奇要了解他们已经睡了多久,更要通过收集一些数据来分析他们的睡眠趋势。现在科技的进步特别在硬件和手机已经带入我们进入了一个全新的时代。
苹果提供了一个很酷的以安全的方式与用户的个人健康信息沟通,并通过内置的应用程序健康安全存储的信息。您不仅可以使用HealthKit建立一个健身的应用程序,该框架还允许您访问睡眠分析数据。
在本教程中,我会给你一个快速介绍HealthKit框架,并演示如何构建睡眠分析简单的应用程序。
介绍
HealthKit提供了一种被称为HealthKit存储加密的数据库结构去存储数据。你能使用HKHealthStore类去访问这个数据库。无论在iPhone上还是Apple Watch上都有他们自己的HealthKit数据存储。健康数据在iPhone上和Apple Watch是同步的。然而为了节省空间Apple Watch上的数据会被周期性的清除。HealthKit和健康APP现在还不可以在iPad上使用。
如果你想根据健康数据创建一个iOS或者watchOS应用,HealthKit是一个强大的工具。它设计的目的是为了管理广泛的数据来源,依据用户的偏好设置自动合并不同的数据来源。应用程序能够访问每一个原始的数据并合并他们。不仅对身体的测量,健身或营养,该数据也可以用于睡眠分析。
对于本文的其余部分,我将告诉你如何在iOS的上去利用HealthKit框架去访问睡眠分析数据。相同的方法也可以使用在watchOS上。请注意本教程使用Swift2.0和XCode7.请确保使用XCode7或者更高的版本。
在继续之前,下载启动项目解压。我已经为你写好了基本的用户界面。当您运行启动项目,你会看到一个计时器UI,你按下启动按钮后,标签上回显示经过的时间。
使用HealthKit框架工作
我们使用这个应用程序的目的是使用开始和暂停按钮保存睡眠数据和读取数据。使用HealthKit你必须在应用开始时候给HealthKit授权。在你的应用程序中,导航到你的当前Target ->功能并打开HealthKit。
接下来,使用下面的代码创建一个HKHealthStore实例在ViewController类中
let healthStore = HKHealthStore()
稍后我们将使用HKHealthStore实例访问HealthKit存储。
正如前面提到的,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存储中:
- 我们需要定义两个NSDate对象来比较开始时间和介绍时间
- 我们使用HKCategoryTypeIdentifierSleepAnalysis创建一个HKObjectType实例
- 我们需要创建一个HKCategorySample类型的实例。您通常使用类别的样本来记录睡眠数据。个体样品代表的时间段,当用户是在床或睡着了。所以我们将创建一个在重复时间段内在床上的样本和睡着的样本。
- 最后我们将会保存这个对象使用HKHealthStore的saveObject方法
编者注:对于样品类型,你需要查看一下[HealthKit Constants Reference](https://developer.apple.com/library/ios/documentation/HealthKit/Reference/HealthKit_Constants/index.html#//apple_ref/doc/uid/TP40014710).
如果你用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
}
})
}
}
这个函数可以在我们需要保存用户睡眠数据的时候调用。
读取睡眠数据
为了读取用户数据,我们需要新建一个查询。你应该首先为HKCategoryTypeIdentifierSleepAnalysis定义一个HKObjectType类别。你可能还需要一个谓词去过滤这些重复数据,你可能还需要一个谓词来筛选使用开始日期和结束日期对应的NSDate对象来检索时间范围内的数据。您还需要建立一种描述排序的检索查询,选择想要的结果。
你的睡眠分析代码应该是这样的:
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)
}
}
这些代码查询HeatherKit所有的睡眠数据然后以降序排列。每个查询都打印出来了开始日期和结束日期的值类型。在床上或者睡觉。我已经设置了30的上限,至少读取30组样品数据。你也可以使用谓词函数去自定义选择你自己的开始日期和结束日期。
测试应用程序
对于这个演示程序,在你点击开始按钮之后我们使用NSTimer来展示已经过去的时间。NSDate对象被创建在你点击了开始按钮之后,睡眠数据被保存在你点击了结束按钮之后。在暂停的方法中你可以调用saveSleepAnalysis()和retrieveSleepAnalysis()方法去保存和获取睡眠数据。
@IBAction func stop(sender: AnyObject) {
endTime = NSDate()
saveSleepAnalysis()
retrieveSleepAnalysis()
timer.invalidate()
}
在您的应用程序,你可能要改变的NSDate对象来选择相关的开始和结束时间(可能不同),保存在床上和睡着的值。
如果你做了更改,您可以运行演示应用程序,并开始计时。让它开始运行几分钟然后点击暂停按钮。然后打开健康APP,你就会看到睡眠数据:
HealthKit应用的建议
HealthKit能够很轻松地为开发人员提供一个共享的平台和访问用户的数据,避免数据中的任何可能的重复或不一致。苹果的审核指导使用HealthKit并要求读/写权限,非常具体的表明可能导致被拒绝的应用程序。
在健康应用程序中保存假的或者不正确的数据也可能会被拒绝。这意味着你不能像本教程这样把你的健康分析算法写的这么简单。你应该尝试使用内置的传感器数据读取和处理任何参数,以避免错误的计算数据。
完整的项目你可以从这里下载.