今天愕把,睡眠的變革是一種時(shí)尚拣凹,用戶比以往任何時(shí)候都好奇要了解他們已經(jīng)睡了多久森爽,更要通過收集一些數(shù)據(jù)來分析他們的睡眠趨勢(shì)。現(xiàn)在科技的進(jìn)步特別在硬件和手機(jī)已經(jīng)帶入我們進(jìn)入了一個(gè)全新的時(shí)代嚣镜。
蘋果提供了一個(gè)很酷的以安全的方式與用戶的個(gè)人健康信息溝通爬迟,并通過內(nèi)置的應(yīng)用程序健康安全存儲(chǔ)的信息。您不僅可以使用HealthKit建立一個(gè)健身的應(yīng)用程序菊匿,該框架還允許您訪問睡眠分析數(shù)據(jù)付呕。
在本教程中,我會(huì)給你一個(gè)快速介紹HealthKit框架跌捆,并演示如何構(gòu)建睡眠分析簡(jiǎn)單的應(yīng)用程序徽职。
介紹
HealthKit提供了一種被稱為HealthKit存儲(chǔ)加密的數(shù)據(jù)庫結(jié)構(gòu)去存儲(chǔ)數(shù)據(jù)。你能使用HKHealthStore類去訪問這個(gè)數(shù)據(jù)庫佩厚。無論在iPhone上還是Apple Watch上都有他們自己的HealthKit數(shù)據(jù)存儲(chǔ)姆钉。健康數(shù)據(jù)在iPhone上和Apple Watch是同步的。然而為了節(jié)省空間Apple Watch上的數(shù)據(jù)會(huì)被周期性的清除抄瓦。HealthKit和健康A(chǔ)PP現(xiàn)在還不可以在iPad上使用潮瓶。
如果你想根據(jù)健康數(shù)據(jù)創(chuàng)建一個(gè)iOS或者watchOS應(yīng)用,HealthKit是一個(gè)強(qiáng)大的工具钙姊。它設(shè)計(jì)的目的是為了管理廣泛的數(shù)據(jù)來源毯辅,依據(jù)用戶的偏好設(shè)置自動(dòng)合并不同的數(shù)據(jù)來源。應(yīng)用程序能夠訪問每一個(gè)原始的數(shù)據(jù)并合并他們煞额。不僅對(duì)身體的測(cè)量悉罕,健身或營養(yǎng),該數(shù)據(jù)也可以用于睡眠分析立镶。
對(duì)于本文的其余部分壁袄,我將告訴你如何在iOS的上去利用HealthKit框架去訪問睡眠分析數(shù)據(jù)。相同的方法也可以使用在watchOS上媚媒。請(qǐng)注意本教程使用Swift2.0和XCode7.請(qǐng)確保使用XCode7或者更高的版本嗜逻。
在繼續(xù)之前,下載啟動(dòng)項(xiàng)目解壓缭召。我已經(jīng)為你寫好了基本的用戶界面栈顷。當(dāng)您運(yùn)行啟動(dòng)項(xiàng)目,你會(huì)看到一個(gè)計(jì)時(shí)器UI嵌巷,你按下啟動(dòng)按鈕后萄凤,標(biāo)簽上回顯示經(jīng)過的時(shí)間。
使用HealthKit框架工作
我們使用這個(gè)應(yīng)用程序的目的是使用開始和暫停按鈕保存睡眠數(shù)據(jù)和讀取數(shù)據(jù)搪哪。使用HealthKit你必須在應(yīng)用開始時(shí)候給HealthKit授權(quán)靡努。在你的應(yīng)用程序中,導(dǎo)航到你的當(dāng)前Target ->功能并打開HealthKit。
接下來惑朦,使用下面的代碼創(chuàng)建一個(gè)HKHealthStore實(shí)例在ViewController類中
let healthStore = HKHealthStore()
稍后我們將使用HKHealthStore實(shí)例訪問HealthKit存儲(chǔ)兽泄。
正如前面提到的,HealthKit授予用戶對(duì)他們的健康數(shù)據(jù)進(jìn)行控制漾月。所以病梢,你必須先請(qǐng)求用戶的許可才可以訪問(讀/寫)到用戶的睡眠分析數(shù)據(jù)。要做到這一點(diǎn)梁肿,首先導(dǎo)入內(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")
}
}
}
此代碼將提示用戶允許或拒絕請(qǐng)求的權(quán)限蜓陌。當(dāng)回調(diào)完成是你可以處理成功或者失敗,并獲得最終結(jié)果吩蔑。用戶沒有必要授權(quán)你的應(yīng)用所有的授權(quán)护奈。但是你必須在你的應(yīng)用中妥善處理錯(cuò)誤。
但是出于測(cè)試目的哥纫,你必須選擇“允許”選項(xiàng)霉旗,授予應(yīng)用程序權(quán)限訪問設(shè)備上的健康數(shù)據(jù)。
寫睡眠分析數(shù)據(jù)
首先蛀骇,我們?nèi)绾文茏x取睡眠分析數(shù)據(jù)厌秒?根據(jù)蘋果的文檔,每個(gè)睡眠分析樣品僅僅有一個(gè)值擅憔。代表用戶在床上睡了鸵闪,HealthKit能夠在重復(fù)的時(shí)間段中使用超過兩個(gè)或者更多的數(shù)據(jù)。通過比較這些樣品的開始和結(jié)束時(shí)間暑诸,應(yīng)用可以計(jì)算一些次要統(tǒng)計(jì):
- 用戶入睡花費(fèi)的時(shí)間
- 在床上和實(shí)際入睡的百分比
- 用戶在睡覺中醒了多少次
- 總共在床上花費(fèi)多長時(shí)間
簡(jiǎn)單地說蚌讼,你按照下面的方法來分析的睡眠數(shù)據(jù)并保存到HealthKit存儲(chǔ)中:
- 我們需要定義兩個(gè)NSDate對(duì)象來比較開始時(shí)間和介紹時(shí)間
- 我們使用HKCategoryTypeIdentifierSleepAnalysis創(chuàng)建一個(gè)HKObjectType實(shí)例
- 我們需要?jiǎng)?chuàng)建一個(gè)HKCategorySample類型的實(shí)例。您通常使用類別的樣本來記錄睡眠數(shù)據(jù)个榕。個(gè)體樣品代表的時(shí)間段篡石,當(dāng)用戶是在床或睡著了。所以我們將創(chuàng)建一個(gè)在重復(fù)時(shí)間段內(nèi)在床上的樣本和睡著的樣本西采。
- 最后我們將會(huì)保存這個(gè)對(duì)象使用HKHealthStore的saveObject方法
編者注:對(duì)于樣品類型凰萨,你需要查看一下[HealthKit Constants Reference](https://developer.apple.com/library/ios/documentation/HealthKit/Reference/HealthKit_Constants/index.html#//apple_ref/doc/uid/TP40014710).
如果你用Swift翻譯上面的代碼,下面是代碼片段保存用戶在床上和睡著的睡眠數(shù)據(jù)械馆。請(qǐng)把下面代碼放到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
}
})
}
}
這個(gè)函數(shù)可以在我們需要保存用戶睡眠數(shù)據(jù)的時(shí)候調(diào)用胖眷。
讀取睡眠數(shù)據(jù)
為了讀取用戶數(shù)據(jù),我們需要新建一個(gè)查詢霹崎。你應(yīng)該首先為HKCategoryTypeIdentifierSleepAnalysis定義一個(gè)HKObjectType類別珊搀。你可能還需要一個(gè)謂詞去過濾這些重復(fù)數(shù)據(jù),你可能還需要一個(gè)謂詞來篩選使用開始日期和結(jié)束日期對(duì)應(yīng)的NSDate對(duì)象來檢索時(shí)間范圍內(nèi)的數(shù)據(jù)尾菇。您還需要建立一種描述排序的檢索查詢境析,選擇想要的結(jié)果囚枪。
你的睡眠分析代碼應(yīng)該是這樣的:
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所有的睡眠數(shù)據(jù)然后以降序排列。每個(gè)查詢都打印出來了開始日期和結(jié)束日期的值類型簿晓。在床上或者睡覺。我已經(jīng)設(shè)置了30的上限千埃,至少讀取30組樣品數(shù)據(jù)憔儿。你也可以使用謂詞函數(shù)去自定義選擇你自己的開始日期和結(jié)束日期。
測(cè)試應(yīng)用程序
對(duì)于這個(gè)演示程序放可,在你點(diǎn)擊開始按鈕之后我們使用NSTimer來展示已經(jīng)過去的時(shí)間谒臼。NSDate對(duì)象被創(chuàng)建在你點(diǎn)擊了開始按鈕之后,睡眠數(shù)據(jù)被保存在你點(diǎn)擊了結(jié)束按鈕之后耀里。在暫停的方法中你可以調(diào)用saveSleepAnalysis()和retrieveSleepAnalysis()方法去保存和獲取睡眠數(shù)據(jù)蜈缤。
@IBAction func stop(sender: AnyObject) {
endTime = NSDate()
saveSleepAnalysis()
retrieveSleepAnalysis()
timer.invalidate()
}
在您的應(yīng)用程序,你可能要改變的NSDate對(duì)象來選擇相關(guān)的開始和結(jié)束時(shí)間(可能不同)冯挎,保存在床上和睡著的值底哥。
如果你做了更改,您可以運(yùn)行演示應(yīng)用程序房官,并開始計(jì)時(shí)趾徽。讓它開始運(yùn)行幾分鐘然后點(diǎn)擊暫停按鈕。然后打開健康A(chǔ)PP翰守,你就會(huì)看到睡眠數(shù)據(jù):
HealthKit應(yīng)用的建議
HealthKit能夠很輕松地為開發(fā)人員提供一個(gè)共享的平臺(tái)和訪問用戶的數(shù)據(jù)孵奶,避免數(shù)據(jù)中的任何可能的重復(fù)或不一致。蘋果的審核指導(dǎo)使用HealthKit并要求讀/寫權(quán)限蜡峰,非常具體的表明可能導(dǎo)致被拒絕的應(yīng)用程序了袁。
在健康應(yīng)用程序中保存假的或者不正確的數(shù)據(jù)也可能會(huì)被拒絕。這意味著你不能像本教程這樣把你的健康分析算法寫的這么簡(jiǎn)單湿颅。你應(yīng)該嘗試使用內(nèi)置的傳感器數(shù)據(jù)讀取和處理任何參數(shù)载绿,以避免錯(cuò)誤的計(jì)算數(shù)據(jù)。
完整的項(xiàng)目你可以從這里下載.