Using Sleep Analysis in Healthkit with Swift

作者:Martin_Joy,原文鏈接,原文日期:2016-06-18

當今厕氨,睡眠革命是一種新潮,用戶們比以往更好奇他們的睡眠時間创橄,還想收集一段時期內的數據,用以分析睡眠趨勢莽红⊥孜罚科技的發(fā)展,尤其是硬件和手機的發(fā)展安吁,給這個看似持續(xù)熱議的學科帶來了新的曙光醉蚁。

Apple 提供了一種很酷的方式,可以安全地訪問用戶的健康信息鬼店,并把它們存儲在內置的健康應用中网棍。有了HealthKit框架,你不僅可以去搭建一個健身應用妇智,還可以去訪問睡眠分析數據确沸。

在這篇教程中,我將對HealthKit框架有一個快速的介紹俘陷,并向你展示如何去搭建一個具有睡眠分析功能的簡單應用。

簡介

HealthKit框架提供一個叫HealthKit store的加密數據庫用以存儲數據
观谦。你可以通過使用HKHealthStore類去訪問這個數據庫拉盾。iPhoneApple Watch都有他們自己的HealthKit store。用戶健康狀況的數據會在Apple WatchiPhone之間同步豁状,然而捉偏,為了節(jié)省空間倒得,舊數據會被周期性地從Apple Watch 中清除。HealthKit 和 健康類 APP 不支持在 ipad 上使用夭禽。

如果你想基于健康數據去創(chuàng)建一個iOS 或者 watchOS app 霞掺,HealthKit 是一個可以幫到忙的強大工具。它可以管理多渠道的數據讹躯,并且根據用戶的偏好自動地合并不同來源的數據菩彬。這些健康類App 可以訪問各個來源的原生數據,同時合并數據潮梯。這些數據不僅可以表明身體健康指標骗灶,健身和營養(yǎng)狀況,還可以用來分析睡眠狀態(tài)秉馏。

這篇文章的剩下內容耙旦,我將向你展示如何在iOS系統上使用HealthKit框架去存儲和訪問睡眠分析的數據。同樣這些方法在watchOS上也是有效萝究。請注意這篇教程的編程環(huán)境是 Swift 2.0Xcode 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)的樣本送朱。
  • 最后,我們將使用HKHealthStoresaveObject方法去寫入數據干旁。

筆者注:對于類別樣本的類型驶沼,可以看看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實例复旬。你也可能想要使用一個斷言,通過startDateendDate這兩個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ā)者提供了一個平臺矮湘,可以方便地共享和訪問用戶數據,同時也避免了訪問數據時出現的重復性和差異性問題乱顾。蘋果對于使用HealthKitapp的審核是非常嚴格板祝,倘若你申請讀寫權限,但是你沒有明確的提示走净,可能會遭到appstore的拒絕券时。

倘若你的app存儲偽數據或不準確的數據,也將會遭到appstore的拒絕伏伯。這意味著橘洞,你不能使用類似于本教程中的睡眠分析數據,你需要通過準確的算法去計算與健康有關的數據说搅≌ㄔ妫或許你嘗試使用設備中內置傳感器的統計數據,加以分析,得出分析數據适肠,以避免出現錯誤或不準確數據霍衫。

對于完成的工程,你可以從這里獲取到代碼侯养。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末敦跌,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子逛揩,更是在濱河造成了極大的恐慌柠傍,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,252評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件辩稽,死亡現場離奇詭異惧笛,居然都是意外死亡,警方通過查閱死者的電腦和手機逞泄,發(fā)現死者居然都...
    沈念sama閱讀 94,886評論 3 399
  • 文/潘曉璐 我一進店門患整,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人炭懊,你說我怎么就攤上這事并级。” “怎么了侮腹?”我有些...
    開封第一講書人閱讀 168,814評論 0 361
  • 文/不壞的土叔 我叫張陵嘲碧,是天一觀的道長。 經常有香客問我父阻,道長愈涩,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,869評論 1 299
  • 正文 為了忘掉前任加矛,我火速辦了婚禮履婉,結果婚禮上,老公的妹妹穿的比我還像新娘斟览。我一直安慰自己毁腿,他們只是感情好,可當我...
    茶點故事閱讀 68,888評論 6 398
  • 文/花漫 我一把揭開白布苛茂。 她就那樣靜靜地躺著已烤,像睡著了一般。 火紅的嫁衣襯著肌膚如雪妓羊。 梳的紋絲不亂的頭發(fā)上胯究,一...
    開封第一講書人閱讀 52,475評論 1 312
  • 那天,我揣著相機與錄音躁绸,去河邊找鬼裕循。 笑死臣嚣,一個胖子當著我的面吹牛,可吹牛的內容都是我干的剥哑。 我是一名探鬼主播硅则,決...
    沈念sama閱讀 41,010評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼星持!你這毒婦竟也來了抢埋?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,924評論 0 277
  • 序言:老撾萬榮一對情侶失蹤督暂,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后穷吮,有當地人在樹林里發(fā)現了一具尸體逻翁,經...
    沈念sama閱讀 46,469評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,552評論 3 342
  • 正文 我和宋清朗相戀三年捡鱼,在試婚紗的時候發(fā)現自己被綠了八回。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,680評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡驾诈,死狀恐怖缠诅,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情乍迄,我是刑警寧澤管引,帶...
    沈念sama閱讀 36,362評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站闯两,受9級特大地震影響褥伴,放射性物質發(fā)生泄漏。R本人自食惡果不足惜漾狼,卻給世界環(huán)境...
    茶點故事閱讀 42,037評論 3 335
  • 文/蒙蒙 一重慢、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧逊躁,春花似錦似踱、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,519評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至念脯,卻和暖如春狞洋,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背绿店。 一陣腳步聲響...
    開封第一講書人閱讀 33,621評論 1 274
  • 我被黑心中介騙來泰國打工吉懊, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留庐橙,地道東北人。 一個月前我還...
    沈念sama閱讀 49,099評論 3 378
  • 正文 我出身青樓借嗽,卻偏偏與公主長得像态鳖,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子恶导,可洞房花燭夜當晚...
    茶點故事閱讀 45,691評論 2 361

推薦閱讀更多精彩內容