Using Sleep Analysis in HealthKit With Swift
使用Swift通過HealthKit框架進行睡眠分析
作者:ANUSHK MITTAL,原文鏈接,原文日期:2016-06-18
Today, Sleep Revolution is a fad and users are curious than ever to not only know about the the time they’ve been asleep but also to analyze the data gathered over a period to reveal their sleeping trends. Advancements in technology including hardwares, and mobiles in particular have brought this seemingly ever-growing subject into a whole new light.
目前脑融,睡眠革命成為一種狂潮,人們比以往更加關注,不僅要知道他們睡眠的時間庸毫,還要分析一段時間內收集的數(shù)據(jù)以觀察睡眠趨勢冠跷。隨著科技特別是硬件和手機的不斷發(fā)展,人們看到了新的曙光厨诸。
Apple provides a cool way to communicate with user’s personal health information in a secure manner and store the information securely through the built-in Health app. Not only can you use HealthKit to build a fitness app
, the framework also allows you access sleep analysis data.
蘋果提供了一種很炫酷的方式來讓用戶個人健康信息在安全的方式下傳遞镶殷,并且通過內置的Health應用安全的存儲信息。你不僅可以使用HealthKit創(chuàng)建一個健康應用微酬,也使用框架訪問睡眠分析數(shù)據(jù)绘趋。
In this tutorial, I will give you a quick introduction to the HealthKit framework, and demonstrate how you can build a simple app for sleep analysis.
在這篇指南,我會讓你對HealthKit框架進行一個快速的入門颗管,并且演示如何創(chuàng)建一個睡眠分析的簡單應用陷遮。
Introduction
介紹
The HealthKit framework provides a structure to save data in an encrypted database called the HealthKit store. You can access this database using the HKHealthStore
class. Both iPhone and Apple Watch have their own HealthKit store. Health data is synced between Apple Watch and iPhone; however, old data is periodically purged from Apple Watch to save space. HealthKit and the Health app are unavailable on iPad.
HealthKit框架提供了一種結構來存儲數(shù)據(jù)到被稱為HealthKit store的加密數(shù)據(jù)庫。你可以使用HKHealthStore
類來訪問這個數(shù)據(jù)庫垦江。iPhone和Apple Watch都有他們各自的HealthKit store帽馋。健康數(shù)據(jù)在Apple Watch和iPhone之間進行同步;然而比吭,舊的數(shù)據(jù)會被定期清理以節(jié)省空間绽族。HealthKit和Health應用均不支持iPad。
HealthKit is a powerful tool if you want to create an iOS or watchOS app based on health data. It is designed to manage data from a wide range of sources, automatically merging the data from different sources based on user’s preferences. Apps can also access the raw data for each source, and merge the data themselves. Not only for body measurements, fitness or nutrition, the data can also be used for sleep analysis.
如果你想開發(fā)一款基于健康數(shù)據(jù)的iOS或watchOS應用梗逮,那么HealthKit無疑是一個強有力的工具项秉。HealthKit被設計用于管理大范圍的數(shù)據(jù)來源,并根據(jù)用戶設定自動合并處理慷彤。應用也可以訪問每一個來源的raw數(shù)據(jù)娄蔼,并且自己合并數(shù)據(jù)怖喻。這些數(shù)據(jù)不僅用于身體測量、健康或營養(yǎng)岁诉,還可以被用來做睡眠分析锚沸。
For the rest of the article, I will show you how to make use of the HealthKit framework for saving and accessing sleep analysis data on iOS. The same methods are applicable for watchOS applications as well. Please note that the tutorial is written using Swift 2.0 and Xcode 7. So make sure you use Xcode 7 (or up) to follow the tutorial.
文章的剩下部分,我將向你展示如何利用HealthKit框架來保存和訪問iOS上的睡眠數(shù)據(jù)涕癣。在watchOS上可以用相同的方法哗蜈。請注意這篇指南是基于Swift 2.0和Xcode 7寫作的。所以請您遵守指南使用Xcode7(或以上)版本坠韩。
Before moving on, download the starter project and unzip it. I have already created the user interface with basic functionalities for you. When you run the starter project, you will see a timer UI that shows the time elapsed after you push the start button.
在開始之前距潘,下載上手項目并解壓。我已經(jīng)為你創(chuàng)建了基本功能的用戶界面只搁。當你運行上手項目音比,你按下按鈕后將會看到按下按鈕之后經(jīng)過時間的計數(shù)器界面。
Working with the HealthKit Framework
使用HealthKit框架
Our aim with the application is to save sleep analysis information and retrieve the data using the Start
& Stop
buttons. To use HealthKit, you must begin by granting the HealthKit capabilities to your app bundle. In your app project, navigate to your current target -> capabilities and turn on HealthKit.
我們應用的目標是使用Start
和Stop
按鈕保存睡眠分析信息和獲取數(shù)據(jù)氢惋。你必須在應用bundle中打開允許獲取HealthKit的權限方可使用HealthKit洞翩。在你的應用項目,選擇當前的target -> capabilities并且打開HealthKit焰望。
Next, you will need to create an instance of HKHealthStore in the ViewController class using the following code:
接下來骚亿,你需要使用下面的代碼在ViewController
中創(chuàng)建一個HKHealthStore
實例:
let healthStore = HKHealthStore()
Later we will use the HKHealthStore
instance to access the HealthKit
store.
然后我們使用HKHealthStore
實例訪問HealthKit store。
As mentioned, HealthKit grants users control over their health data. So you have to first request users’ permission before you can gain access (write/read) to the Sleep Analysis data of the user. To do so, first import the built-in HealthKit
framework and update the viewDidLoad
method like this:
需要提及一點的是HealthKit收集健康數(shù)據(jù)是根據(jù)用戶的設置熊赖。所以你必須在你第一次獲取讀寫睡眠分析數(shù)據(jù)的時候請求用戶權限来屠。要做到這點,首先導入內置的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")
}
}
}
This code will prompt the user to allow or deny the requested permissions. With the completion block, you can handle success or error and get the final result. It is not necessary that the user grants your app all the requested permissions. You must handle the errors gracefully in your app.
這段代碼可以提示用戶允許或者拒絕權限請求的妖。通過completion block绣檬,你可以處理success或者error信息并且得到最后的結果足陨。并不需要用戶獲得所有的請求權限。你必須在應用優(yōu)雅的處理錯誤信息娇未。
But for testing purpose, you must have to select the “Allow” option to grant the app permission to access the health data on your device.
但是對于測試目的墨缘,你必須選擇“Allow”選項來授權應用獲取你設備上健康數(shù)據(jù)的訪問權限。
Writing Sleep Analysis Data
存儲睡眠分析數(shù)據(jù)
First, how can we retrieve the sleep analysis data? According to Apple’s documentation, each sleep analysis sample can have only one value. To represent the user being both in bed and asleep, HealthKit uses two or more samples with overlapping times. By comparing the start and end times of these samples, apps can calculate a number of secondary statistics:
首先零抬,我們如何獲取睡眠分析數(shù)據(jù)镊讼?根據(jù)蘋果的文檔,每一個睡眠分析樣本只有1個值平夜。為了展示用戶躺在床上和睡眠的時間蝶棋,HealthKit使用2個或更多的重疊時間。通過比較開始和結束的樣本忽妒,應用可以計算出大量的次級統(tǒng)計數(shù)據(jù):
- the amount of time it takes for the user to fall asleep(用戶睡著的時間)
- the percentage of time in bed that the user actually sleeps(用戶在床上真正睡眠時間所占的比例)
- the number of times the user wakes up while still in bed(用戶躺在床上醒來的次數(shù))
- the total amount of time spent both in bed and asleep(躺在床上和睡眠的總時間)
In brief, you follow the below approach to save sleep analysis data to the HealthKit store:
簡而言之玩裙,你可以遵循下面方式來保存睡眠分析數(shù)據(jù)到HealthKit sotore
:
- We need to define two
NSDate
objects corresponding to the start time and the end time.(我們需要定義兩個跨越開始時間和結束時間的NSDate
對象) - We then create an instance of
HKObjectType
usingHKCategoryTypeIdentifierSleepAnalysis
.(下來我們使用HKCategoryTypeIdentifierSleepAnalysis
來創(chuàng)建HKObjectType
實例) - We need to create a new object of the
HKCategorySample
type. You normally use category samples to record sleep data. Individual samples represent time periods when the user is in bed or asleep. So we will create both an in-bed sample and an asleep sample with overlapping times.( 我們需要創(chuàng)建一個HKCategorySample
類型兼贸。你通常需要使用category samples記錄睡眠數(shù)據(jù)。用戶可以個性化的展示躺在床上或者睡眠的時間段吃溅。所以我們將要創(chuàng)建躺在床上和睡眠的重疊時間溶诞。) - Finally, we’ll save the object using
saveObject
ofHKHealthStore
.(最后我們需要使用HKHealthStore
的saveObject
來保存對象)
Editor’s note: For the type of the sample, you can look it up in HealthKit Constants Reference.
編者注: 對于樣本的類型, 你可以在HealthKit Constants Reference里面查詢.
If you translate the above into Swift, here is the code snippet to save sleep analysis data for both in bed and asleep values. Please insert the method in the ViewController
class:
如果你將上面所述轉換為Swift,這段代碼可以保存在床上和睡眠的分析數(shù)據(jù)决侈。請?zhí)砑釉摲椒ǖ?code>ViewController類:
func saveSleepAnalysis() {
// alarmTime and endTime are NSDate objects
// alarmTime和endTime是NSDate對象
if let sleepType = HKObjectType.categoryTypeForIdentifier(HKCategoryTypeIdentifierSleepAnalysis) {
// we create our new object we want to push in Health app
//我們創(chuàng)建新對象push到Health應用
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
}
})
}
}
This function can be called at the time we want to save the Sleep Analysis data to HealthKit.
每當我們想要保存睡眠分析數(shù)據(jù)到HealthKit的時候都可以調用。
Reading Sleep Analysis Data
讀取睡眠分析數(shù)據(jù)
To read the sleep analysis data, we will need to create a query. You should begin by defining the HKObjectType
category to HKCategoryTypeIdentifierSleepAnalysis
. You may also want to use a predicate to filter the retrieved data using startDate
and endDate
which are NSDate objects corresponding to the time range that you may want to retrieve. You will also need to create a sortDescriptor
for sorting the retrieved queries to select the desired result.
為了獲取睡眠分析數(shù)據(jù)赖歌,我們需要創(chuàng)建一個查詢(query)枉圃。你應該通過定義HKCategoryTypeIdentifierSleepAnalysis
的類目HKObjectType
。你可能也需要使用predicete來過濾獲取的數(shù)據(jù)庐冯,使用startDate
和endDate
NSDate對象檢索你可能需要的時間范圍讯蒲。你可能也需要創(chuàng)建一個sortDescriptos
來對獲取的查詢進行排序以得到想要的結果。
Your code for retrieving sleep analysis data should look like this:
你獲取睡眠合理數(shù)據(jù)的代碼可能如下:
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
// 首先使用一個sortDescriptos獲取最近的數(shù)據(jù)
let sortDescriptor = NSSortDescriptor(key: HKSampleSortIdentifierEndDate, ascending: false)
// we create our query with a block completion to execute
//我們創(chuàng)建一個blcok來查詢
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
//對數(shù)據(jù)做一些處理
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)
}
This code queries the HealthKit to get all Sleep Analysis data and then sorts it down to descending order. Then each query is printed with the startDate and endDate along with the type of value i.e. In Bed or Asleep. I have set the limit to 30 to retrieve the last 30 recorded samples. You can also use the predicate method to choose your custom start and end dates.
這段代碼通過HealthKit獲得全部睡眠分析數(shù)據(jù)墨林,然后做降序。接下來對每一個查詢按照在床上或者睡眠的開始和結束日期打印值犯祠。我設置限制最多30條以獲取最近的30條數(shù)據(jù)旭等。你也可以使用predicate方法來自定義開始和結束日期。
App Testing
App 測試
For the demo application, I have used an NSTimer to show the time elapsed since you push the start button. The NSDate
objects are created on the start and end buttons to save sleep analysis data as the elapsed time. In the stop
action method, you can invoke the saveSleepAnalysis()
and retrieveSleepAnalysis()
methods to save and get the sleep data.
對于Demo應用衡载,我已經(jīng)用一個NSTimer來展示自從你按下開始按鈕所經(jīng)過的時間搔耕。NSDate
對象在按下開始按鈕的創(chuàng)建,在按結束按鈕的時候保存睡眠分析數(shù)據(jù)痰娱。在stop方法中弃榨,你可以調用saveSleepAnalysis()
和retrieveSleepAnalysis()
方法來保存和獲取睡眠數(shù)據(jù)。
@IBAction func stop(sender: AnyObject) {
endTime = NSDate()
saveSleepAnalysis()
retrieveSleepAnalysis()
timer.invalidate()
}
In your apps, you may want to change the NSDate objects to choose relevant start and end times (probably different) for saving the in bed and asleep values.
在你的應用中梨睁,你可能想要想要NSDate對象來選擇有意義的開始和結束的時間段(可能不同)來存儲躺在床上和睡眠的值鲸睛。
Once you’ve made the changes, you can run the demo app and start the timer. Let it run for a few minutes and then tap the Stop button. After that, open the Health app. You’ll find the sleep data in there.
一旦你做出改變,你可以運行demo應用并開啟計時器坡贺。讓它跑幾分鐘官辈,然后按下stop按鈕。接下來打開Health應用遍坟,你將會在里面找到睡眠數(shù)據(jù)拳亿。
Some Advices for HealthKit Apps
對HealthKit 應用的一些建議
HealthKit is designed to provide a common platform for app developers to share and access user’s data easily and avoids any possible duplication or inconsistency in data. Apple review guidelines are very specific for apps using the HealthKit and requesting read/write permissions without a clear demonstration of their use might result in the app being rejected.
HealthKit被設計為公共平臺讓應用開發(fā)者更方便分享和訪問避免可能的重復和不一致的數(shù)據(jù)。蘋果審核指南中對于使用HealthKit和請求讀寫權限愿伴,但是沒有一個明確的聲明可能會被拒絕肺魁。
Apps that save fake or incorrect data to the Health App would also be rejected. This means, that you cannot be na?ve with your algorithms for calculating different health values like sleep analysis in this tutorial. You should try using the inbuilt sensor data for reading and manipulating any parameters to avoid calculating false data.
應用保存無效或者錯誤的數(shù)據(jù)到Health App也可能會被拒絕。這就意味著隔节,你不能像指南中的睡眠數(shù)據(jù)一樣用你的算法計算不同的健康值鹅经。你應該嘗試去讀和操作內置的傳感器數(shù)據(jù)胡桨,以避免錯誤的數(shù)據(jù)。
For the complete Xcode project, you can get it here.
對于完整的Xcode項目瞬雹,你可以在這里獲取昧谊。