作者:ANUSHK MITTAL,原文鏈接,原文日期:2016-01-18
譯者:Wiilen
如今,對睡眠監(jiān)測的創(chuàng)新已經(jīng)成為一種潮流。用戶比以前更加好奇,他們不僅想知道自己的睡眠時間,更想對一段時間內(nèi)收集的數(shù)據(jù)進行分析,來了解自己的睡眠趨勢。科技的發(fā)展也帶動了硬件的發(fā)展,其中特別是手機的發(fā)展,使得睡眠分析這一進步緩慢的領(lǐng)域有了全面的發(fā)展。
蘋果公司提供了一種酷炫的方式,可以安全地與用戶的個人健康信息進行交互,并將這些信息安全地存入內(nèi)置的 Health App。你不僅可以使用 HealthKit 框架來開發(fā)一個健康類 App,也可以通過它來訪問睡眠分析數(shù)據(jù)。
在這個教程中,我將為你快速介紹 HealthKit 框架,并演示如何開發(fā)一個用于睡眠分析的簡單 App。
介紹
HealthKit 框架提供了一種結(jié)構(gòu),用于將數(shù)據(jù)存入名為 HealthKit store 的加密的數(shù)據(jù)庫。你可以使用HKHealthStore
類來訪這個數(shù)據(jù)庫。iPhone 與 Apple Watch 都有自己的 HealthKit store。健康數(shù)據(jù)能夠在 Apple Watch 與 iPhone 中進行同步,而舊數(shù)據(jù)會周期性地從 Apple Watch 中清除以節(jié)約空間。HealthKit 與 Health App 在 iPad 上無法使用。
HealthKit 是一個強大的工具,可以幫助你開發(fā)基于健康數(shù)據(jù)的 iOS 或 watchOS App。它專門用于管理各種來源的數(shù)據(jù),根據(jù)用戶偏好,它能自動合并不同來源的數(shù)據(jù)。Apps 也可以訪問不同來源的原始數(shù)據(jù),自己合并這些數(shù)據(jù)。這些數(shù)據(jù)不僅可用于身體測量、健康數(shù)據(jù)或營養(yǎng)攝入監(jiān)測,也可以用于睡眠分析。
在這篇文章之后的部分,我將演示在 iOS 上如何使用 HealthKit 框架存儲和訪問睡眠分析數(shù)據(jù)。這些方法也可用在 watchOS App 上。請注意這篇教程中使用的是 Swift 2.0 與 Xcode 7。為了完成這篇教程,你需要確保你使用的是 Xcode 7 或以上版本。
在開始之前,下載初始工程并解壓它。我已經(jīng)為你創(chuàng)建了具有基本功能的 UI。運行這個工程,你可以看到一個計時器 UI,在你點擊開始按鈕之后,它會開始計時。
使用 HealthKit 框架
這個 Apps 的目的是保存睡眠分析數(shù)據(jù),并使用start
與Stop
按鈕來獲取這些數(shù)據(jù)。要使用 HealthKit,你首先需要允許在 app bundle 中使用 HealthKit。在你的項目中,導(dǎo)航到 target -> capabilities 并開啟 HealthKit。
下一步,你需要使用以下代碼在ViewController
中創(chuàng)建一個HKHealthStore
的實例:
let HealthStore = HKHealthStore()
之后我們會使用HKHealthStore
實例來訪問 HealthKit store。
前面提到過,HealthKit 允許用戶控制他們的健康數(shù)據(jù)。所以你首先需要獲得用戶授權(quán),才能訪問(讀/寫)用戶睡眠分析數(shù)據(jù)。要做到這一點,先 import 內(nèi)置的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")
}
}
}
這部分代碼會提示用戶允許或拒絕授權(quán)。在 completion block 中,你可以處理成功或錯誤信息,并獲取最終結(jié)果。用戶不需要給予你的 App 所請求的全部權(quán)限,你需要在 App 中優(yōu)雅地處理錯誤。
但為了方便測試,你需要選擇“允許”來授權(quán)你的 App 訪問設(shè)備上的健康數(shù)據(jù)。
寫入睡眠分析數(shù)據(jù)
首先,我們?nèi)绾潍@取睡眠分析數(shù)據(jù)?根據(jù)蘋果公司的文檔,每個睡眠分析樣本數(shù)據(jù)只含有一個值。HealthKit 使用兩個或以上在時間上重疊的樣本數(shù)據(jù),來表示用戶躺在床上并處于睡眠中。通過對比這些樣本數(shù)據(jù)的開始及結(jié)束時間,App 可以計算出一些二級統(tǒng)計數(shù)據(jù):
- 用戶入睡所需要的時間
- 用戶躺在床上的時間里,實際睡著的時間所占的百分比
- 用戶仍躺在床上時,醒過來的次數(shù)
- 用戶在床上度過的時間和睡眠時間的總和
簡單來說,你需要使用以下方法將睡眠分析數(shù)據(jù)存入 HealthKit Store:
- 我們需要定義兩個
NSDate
對象,對應(yīng)到開始時間與結(jié)束時間。 - 之后使用
HKCategoryTypeIdentifierSleepAnalysis
來創(chuàng)建一個HKObjectType
實例。 - 我們需要創(chuàng)建一個類型為
HKCategorySample
的新對象。你通常使用類別樣本(Category Sample)來記錄睡眠數(shù)據(jù)。獨立樣本(Individual Sample)用來表示在某些時間段中,用戶躺在床上或處于睡眠中。所以我們需要創(chuàng)建一個記錄用戶躺在床上時間(In bed)的樣本與一個記錄用戶處于睡眠中(Asleep)的樣本,這兩個樣本可能會有部分時間重疊。 - 最后,我們使用
HKHealthStore
類中的saveObject
方法來保存對象。
編輯提示:關(guān)于樣本的類型,你可以在HealthKit Constants Reference中找到更多詳細信息。
如果你想要將上述文字翻譯成 Swift 代碼,下面是部分代碼,用于保存睡眠分析數(shù)據(jù),包括在床上度過的時間數(shù)據(jù)和睡眠時間的數(shù)據(jù)。請將下列方法插入到ViewController
中:
func saveSleepAnalysis() {
// alarmTime 和 endTime 都是 NSDate 對象
if let sleepType = HKObjectType.categoryTypeForIdentifier(HKCategoryTypeIdentifierSleepAnalysis) {
// 我們創(chuàng)建一個新的對象,并將它導(dǎo)入到 Health app 中
let object = HKCategorySample(type:sleepType, value: HKCategoryValueSleepAnalysis.InBed.rawValue, startDate: self.alarmTime, endDate: self.endTime)
// 最后,我們保存這個對象
healthStore.saveObject(object, withCompletion: { (success, error) -> Void in
if error != nil {
// 錯誤處理
return
}
if success {
print("My new data was saved in HealthKit")
} else {
// 另一個錯誤處理
}
})
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 {
// 錯誤處理
return
}
if success {
print("My new data (2) was saved in HealthKit")
} else {
// 另一個錯誤處理
}
})
}
}
我們想要將睡眠分析數(shù)據(jù)存入 HealthKit 時,可以調(diào)用這個函數(shù)。
讀取睡眠分析數(shù)據(jù)
為了讀取睡眠分析數(shù)據(jù),我們將創(chuàng)建一個請求。你需要從使用HKCategoryTypeIdentifierSleepAnalysis
來創(chuàng)建一個HKObjectType
類的實例開始。你可能想使用 predicate,通過startDate
和endDate
這些詞來過濾獲取的數(shù)據(jù),這是一些對應(yīng)到某些時間段的NSDate
對象。你也需要創(chuàng)建一個sortDescriptor
來對獲取數(shù)據(jù)的請求進行排序,以選出你需要的結(jié)果。
用于獲取睡眠分析數(shù)據(jù)的代碼如下:
func retrieveSleepAnalysis() {
// 首先,我們定義需要的對象類型
if let sleepType = HKObjectType.categoryTypeForIdentifier(HKCategoryTypeIdentifierSleepAnalysis) {
// 使用 sortDescriptor 來獲取時間由近到遠的數(shù)據(jù)
let sortDescriptor = NSSortDescriptor(key: HKSampleSortIdentifierEndDate, ascending: false)
// 創(chuàng)建查詢請求,以及一個 completion block
let query = HKSampleQuery(sampleType: sleepType, predicate: nil, limit: 30, sortDescriptors: [sortDescriptor]) { (query, tmpResult, error) -> Void in
if error != nil {
// 錯誤處理
return
}
if let result = tmpResult {
// 處理取得的數(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)")
}
}
}
}
// 最后,執(zhí)行查詢請求
healthStore.executeQuery(query)
}
}
上面的代碼向 HealthKit 發(fā)出查詢請求,來獲得所有的睡眠分析數(shù)據(jù),再對這些數(shù)據(jù)以時間降序進行排序。之后每條請求打印出了開始時間與結(jié)束時間,并標(biāo)明是在床上度過的類型數(shù)據(jù),或是在睡眠狀態(tài)的類型數(shù)據(jù)。我將請求的時間設(shè)為30,來獲取過去30秒內(nèi)記錄的樣本。你也可以使用 predicate 方法來自定義開始與結(jié)束時間。
App 測試
在這個 demo 中,我使用一個NSTimer
對象,在你點擊了開始按鈕之后進行計時。在開始的時候與結(jié)束的時候,我們各創(chuàng)建了一個NSDate
對象,將睡眠分析數(shù)據(jù)保存為經(jīng)過的時間。在調(diào)用stop
方法時,你可以調(diào)用saveSleepAnalysis()
和retrieveSleepAnalysis()
來保存并獲取睡眠數(shù)據(jù)。
@IBAction func stop(sender: AnyObject) {
endTime = NSDate()
saveSleepAnalysis()
retrieveSleepAnalysis()
timer.invalidate()
}
在你的 App 中,你可能想要改變NSDate
對象,為躺在床上和處于睡眠中這兩種狀態(tài)選擇(可能不同的)開始與結(jié)束時間。
在你做出這些改變之后,你可以運行這個 demo 并啟動計時器。讓它運行一段時間,然后點擊停止按鈕。做完這些之后,打開 Health App,你會發(fā)現(xiàn) App 中出現(xiàn)了睡眠數(shù)據(jù)。
一些關(guān)于 HealthKit App 的建議
HealthKit 提供了一個通用的平臺,通過這個平臺,App 開發(fā)者們可以方便地分享和訪問用戶數(shù)據(jù),避免獲得重復(fù)或不連續(xù)的數(shù)據(jù)。蘋果公司的審核指南中明確指出,對于那些使用了 HealthKit 并請求讀寫權(quán)限的 App,如果沒有明確演示它們的用途,可能會在審核時被拒絕。
那些保存了虛假或錯誤數(shù)據(jù)到 Health App 中的 App,可能也會被拒。這意味著你不能使用自己的算法來計算不同的健康數(shù)據(jù),比如這個教程中的睡眠分析數(shù)據(jù)。你應(yīng)該嘗試讀取內(nèi)建的傳感器數(shù)據(jù),并調(diào)整任意參數(shù)以避免計算出錯誤的數(shù)據(jù)。
你可以點擊這里獲取完整的 Xcode 項目。