作者:Martin_Joy,原文鏈接,原文日期:2016-06-18
當今厕氨,睡眠革命是一種新潮,用戶們比以往更好奇他們的睡眠時間创橄,還想收集一段時期內的數據,用以分析睡眠趨勢莽红⊥孜罚科技的發(fā)展,尤其是硬件和手機的發(fā)展安吁,給這個看似持續(xù)熱議的學科帶來了新的曙光醉蚁。
Apple
提供了一種很酷的方式,可以安全地訪問用戶的健康信息鬼店,并把它們存儲在內置的健康應用中网棍。有了HealthKit
框架,你不僅可以去搭建一個健身應用妇智,還可以去訪問睡眠分析數據确沸。
在這篇教程中,我將對HealthKit
框架有一個快速的介紹俘陷,并向你展示如何去搭建一個具有睡眠分析功能的簡單應用。
簡介
HealthKit
框架提供一個叫HealthKit store
的加密數據庫用以存儲數據
观谦。你可以通過使用HKHealthStore
類去訪問這個數據庫拉盾。iPhone
和Apple Watch
都有他們自己的HealthKit store
。用戶健康狀況的數據會在Apple Watch
和iPhone
之間同步豁状,然而捉偏,為了節(jié)省空間倒得,舊數據會被周期性地從Apple Watch
中清除。HealthKit
和 健康類 APP
不支持在 ipad
上使用夭禽。
如果你想基于健康數據去創(chuàng)建一個iOS
或者 watchOS app
霞掺,HealthKit
是一個可以幫到忙的強大工具。它可以管理多渠道的數據讹躯,并且根據用戶的偏好自動地合并不同來源的數據菩彬。這些健康類App
可以訪問各個來源的原生數據,同時合并數據潮梯。這些數據不僅可以表明身體健康指標骗灶,健身和營養(yǎng)狀況,還可以用來分析睡眠狀態(tài)秉馏。
這篇文章的剩下內容耙旦,我將向你展示如何在iOS
系統上使用HealthKit
框架去存儲和訪問睡眠分析的數據。同樣這些方法在watchOS
上也是有效萝究。請注意這篇教程的編程環(huán)境是 Swift 2.0
和 Xcode 7
免都。所以學習這篇教程的時候,確定自己使用的是Xcode 7
或其更新的版本帆竹。
在開始之前绕娘,下載啟動項目并且解壓它。我已經為你創(chuàng)建了具有基本功能的用戶界面馆揉,當你運行這個啟動項目的時候业舍,你將看到一個計時器,它能展示你按下按鈕后經過的時間升酣。
使用HealthKit框架
我們的應用是想要取回在計時期間的睡眠分析數據舷暮,并保存它。為了使用 HealthKit
噩茄,
你需要獲取使用HealthKit
的許可下面。在你的工程中,選中 SleepAnalysis
绩聘,然后點擊Targets
下方的 SleepAnalysis
沥割。接著,選擇Capabilities
凿菩,并且將HealthKit
移至On
狀態(tài)
接下來机杜,你將需要在ViewController
類中使用下面代碼去創(chuàng)建一個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")
}
}
}
以上代碼將提示用戶去同意或拒絕你的權限請求。在這個閉包中堵未,你可以處理成功或失敗狀態(tài)的回調事件腋舌,并且可以獲得請求的結果。用戶也不一定會同意你app
所有的權限請求渗蟹,所以你必須在app
中合理地處理錯誤块饺。
但是出于測試的目的,你必須選擇“允許”選項來允許應用程序訪問你的設備上的健康數據拙徽。
寫入Sleep Analysis數據
首先刨沦,我們如何能夠拿到睡眠分析數據呢?通過Apple
的文檔膘怕,可以知道每個睡眠分析數據樣本都僅有一個數值想诅。為了表示臥床和睡眠狀態(tài),HealthKit
使用兩個或者更多含有重疊時間的樣本加以分析岛心。通過比較這些樣本的開始和結束時間来破,app
可以得出一些二次統計的數據。
- 用戶花費了多少時間才進入睡眠
- 用戶在床上睡眠時間占全部床上時間的百分比
- 用戶在床上醒來的次數
- 用戶臥床和睡眠的時間的總時間
簡而言之忘古,你按照下面的方法去保存睡眠分析數據到HealthKit Store
- 我們需要定義兩個
NSData
對象去放對應的開始和結束時間 - 我們需要使用
HKCategoryTypeIdentifierSleepAnalysis
去創(chuàng)建一個HKObjectType
實例 - 我們需要去創(chuàng)建一個
HKCategorySample
類型的實例徘禁,你通常會使用這個實例去記錄睡眠數據。單獨的樣本代表這個用戶臥床或睡眠時的時長髓堪。所以我們將創(chuàng)建包含重疊時間的臥床狀態(tài)和睡眠狀態(tài)的樣本送朱。 - 最后,我們將使用
HKHealthStore
的saveObject
方法去寫入數據干旁。
筆者注:對于類別樣本的類型驶沼,可以看看HealthKit官方文檔中的HealthKit常數參考。
這里提供關于保存臥床和睡眠分析數據的代碼片段争群,來幫助你將上述描述轉換為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
中去的時候换薄,就可以調用這個方法玉雾。
讀取睡眠分析數據
如果要去讀取睡眠分析數據,我們將需要創(chuàng)建一個查詢方法轻要。你需要創(chuàng)建一個HKCategoryTypeIdentifierSleepAnalysis
類型的HKObjectType
實例复旬。你也可能想要使用一個斷言,通過startDate
和endDate
這兩個NSData
對象對應的時間范圍來過濾取回的數據冲泥。你同時也需要去創(chuàng)建一個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)
}
}
以上的代碼先查詢到所有的睡眠分析的數據幸冻,并按照降序排列。每個查詢結果將被打印出來咳焚,打印結果包含開始時間洽损、結束時間、以及所對應的類別(臥床或睡眠)革半。我已經設置了限制碑定,取回最近的三十條記錄樣本。你可以使用自己的斷言方法自定義開始時間和結束時間來限制查詢的區(qū)間又官。
應用測試
對于 demo
程序延刘,我已經使用了一個NSTimer
去顯示點擊開始按鈕后流逝的時間。NSDate
對象被創(chuàng)建用來保存開始和結束之間的睡眠分析數據六敬。在stop
方法中碘赖,你可以調用saveSleepAnalysis()
方法和retrieveSleepAnalysis()
方法去保存和獲取睡眠數據。
@IBAction func stop(sender: AnyObject) {
endTime = NSDate()
saveSleepAnalysis()
retrieveSleepAnalysis()
timer.invalidate()
}
然而在你個人的應用中外构,你或許會通過改變對應的NSDate
對象普泡,從而選擇相應的開始時間和多個(不同的)結束時間來記錄個人臥床和睡眠狀態(tài)的數據。
當你完成調整后审编,你可以運行這個demo
并開始計時撼班,讓他運行幾分鐘,然后點擊stop
按鈕垒酬。之后砰嘁,打開這款健康應用,你將發(fā)現那里的睡眠數據勘究。
對于健康類app的一些建議
HealthKit
為給開發(fā)者提供了一個平臺矮湘,可以方便地共享和訪問用戶數據,同時也避免了訪問數據時出現的重復性和差異性問題乱顾。蘋果對于使用HealthKit
的app
的審核是非常嚴格板祝,倘若你申請讀寫權限,但是你沒有明確的提示走净,可能會遭到appstore
的拒絕券时。
倘若你的app存儲偽數據或不準確的數據,也將會遭到appstore
的拒絕伏伯。這意味著橘洞,你不能使用類似于本教程中的睡眠分析數據,你需要通過準確的算法去計算與健康有關的數據说搅≌ㄔ妫或許你嘗試使用設備中內置傳感器的統計數據,加以分析,得出分析數據适肠,以避免出現錯誤或不準確數據霍衫。
對于完成的工程,你可以從這里獲取到代碼侯养。