如何使用Swift來學習HealthKit中的sleep analysis

Source

如何使用Swift來學習HealthKit中的sleep analysis

如今,有關睡眠的問題變得流行起來,用戶不僅對他們什么時候入睡感興趣,更關心的是一段時間之后,應用根據(jù)收集的數(shù)據(jù)所得出的結果。隨著硬件和手機技術的發(fā)展,有關科技與睡眠的話題變的極其受關注。

蘋果通過內(nèi)建的Health應用,提供了一種簡單酷炫的方式來安全的訪問和存儲用戶的健康信息。你不僅可以用HealthKit來開發(fā)一個健康類應用,還可以利用framework來獲取有關sleep analysis的數(shù)據(jù)。

在這個教程里,我將帶你快速了解HealthKit的框架,并且演示如何開發(fā)一個簡單的sleep analysis應用。

簡介

HealthKit框架提供了一種結構HealthKit store,利用它你可以把信息存儲在一個加密的數(shù)據(jù)庫里。你可以通過HKHealthStore這個類來訪問數(shù)據(jù)庫。iPhone和Apple Watch分別擁有自己的HealthKit store,并且里面的數(shù)據(jù)在iPhone和Apple Watch之間是同步的。但是有一點需要注意,在Apple Watch中,為了節(jié)省空間,舊的數(shù)據(jù)是會被清除的。而iPad是不支持Health Kit和Health應用的。

你如果想開發(fā)一個iOS或者watchOS的應用,那么HealthKit是一個強大的工具。HealthKit就是被設計用來管理來自不同資源的數(shù)據(jù),而且可以根據(jù)用戶的設置來合并這些數(shù)據(jù)。應用還可以訪問原始數(shù)據(jù),并且合并他們。身體指標,健康指標以及營養(yǎng)指標,這些數(shù)據(jù)都可以被用來做sleep analysis。

接下來,你將會了解如何使用HealthKit框架去保存和訪問iOS中的sleep analysis數(shù)據(jù)。以下的內(nèi)容同樣適用于watchOS。這個教程是基于Swift 2.0 和 Xcode 7. 請確保你是用Xcode 7或者以上的版本。

在這之前,下載初始工程文件并且解壓縮。我已經(jīng)為你創(chuàng)建了基本的界面。當你運行這個工程的時候,你會看到一個計時器的界面,點擊開始按鈕,計時器開始運行。

學習HealthKit框架

這個教程的目標是開發(fā)一個簡單的應用,可以存儲sleep analysis的數(shù)據(jù),以及通過開始 & 停止按鈕來獲取數(shù)據(jù)。第一步,你必須獲得HealthKit的許可。在你的工程文件中,選擇Current Target選項,選擇capabilities,并且打開對應的HealthKit。

HealthKit-allow
HealthKit-allow

下一步,你需要在ViewController中創(chuàng)建一個HKHealthStore實例,下面是代碼:

let healthStore = HKHealthStore()

接著,我們使用創(chuàng)建的HKHealthStore實例來訪問HealthKit store。

就像剛才提到的一樣,HealthKit允許用戶去選擇是否其他程序可以獲取他們的健康數(shù)據(jù)。所以在你訪問(讀/寫)sleep analysis數(shù)據(jù)之前,你需要獲取用戶的許可。怎么做呢?第一步,導入內(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")
        }
    }
}

以上的代碼將會請求獲取用戶的HealthKit權限,用戶可以選擇允許或者拒絕。在完成閉包中,你可以做更多的處理,例如獲取權限成功怎么辦,出現(xiàn)錯誤應該怎么辦。用戶有可能拒絕你的訪問權限,所以你必須要在完成閉包中小心的處理這些特殊情況。

為了教程的順利進行,你必須要選擇允許選項來使應用獲得你手機上的健康數(shù)據(jù)。

Health-App-Permission
Health-App-Permission

寫入sleep analysis數(shù)據(jù)

首先,我們?nèi)绾蔚玫絪leep analysis的數(shù)據(jù)呢?根據(jù)蘋果的官方文檔,每一個sleep analysis的樣本只包含一個值。這個值表示了用戶在床上的時間和睡眠的時間,HealthKit用了二個或者二個以上的樣本,每一個樣本都包含與其它樣本重疊的時間。通過這些樣本的開始時間和結束時間,我們能夠計算出這樣的一些數(shù)據(jù):

  • 用戶入睡用了多長時間
  • 用戶睡眠時間與用戶在床上時間的比例
  • 用戶醒來后直到下床的時間
  • 用戶在床上和用戶睡眠的總共時間
record_sleep_data
record_sleep_data

簡單來說,根據(jù)以下方法,我們能夠把sleep analysis數(shù)據(jù)存入到HealKit store中。

  1. 首先根據(jù)開始時間和結束時間,定義兩個NSDate對象
  2. 利用HKCategoryTypeIdentifierSleepAnalysis創(chuàng)建HKObjectType實例
  3. 創(chuàng)建一個HKCategorySample實例。每一個樣本代表了用戶在床上或者睡眠的時間長度。所以我們創(chuàng)建一個在床上的樣本和睡眠的樣本,這兩個樣本有著沖重疊的時間。
    4.最后,我們用HKHealthStoresaveObject方法來保存這個對象。

如果把上述的4步轉化為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

            }
        })

    }

}

當想要存儲sleep analysis數(shù)據(jù)到HealthKit的時候,我們可以調(diào)用這個方法。

讀取sleep analysis數(shù)據(jù)

為了能夠讀取sleep analysis的數(shù)據(jù),我們需要執(zhí)行一個查詢操作。首先,定義一個HKObjectType類別,指明類別是HKCategoryTypeIdentifierSleepAnalysis。接下來可以用predicate去過濾得到的數(shù)據(jù),可以根據(jù)startDateendDate這兩個NSDate類來得到你想要的時間區(qū)間。最后還創(chuàng)建一個sortDescriptor來根據(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

        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)

    }

}

這個方法用來查詢HealthKit,并且得到所有的sleep analysis數(shù)據(jù),并且把這些數(shù)據(jù)按照降序排序。接下來每一個查詢都以startDate和endDate的形式被打印出來。例如In Bed 或者是 Asleep。 在創(chuàng)建query對象時,我在limit參數(shù)里傳入了30,表示我想得到最后30條記錄的樣本。當然了,你可以用在predicate參數(shù)中,傳入你自己定義的predicate對象,這樣你就可以自定義startDate和endDate了。

應用測試

在這個Demo應用中,我用了一個NSTimer來模擬真實的時間,當你按下開始按鈕后,計時器會運行。兩個NSDate對象在開始和結束按鈕被按下時分別被創(chuàng)建,這樣我們就可以模擬記錄sleep analysis數(shù)據(jù)了。在stop方法中,你可以調(diào)用saveSleepAnalysis()retrieveSleepAnalysis()方法來存儲和讀取睡眠數(shù)據(jù)。

@IBAction func stop(sender: AnyObject) {

    endTime = NSDate()

    saveSleepAnalysis()

    retrieveSleepAnalysis()

    timer.invalidate()

}

在你的工程文件中,你不用完全遵循我的代碼,你也可以自由的改變startDate和endDate這兩個NSDate對象去存儲用戶在床上的時間和睡眠時間。

好了,現(xiàn)在你可以運行你的程序,開始計時。讓我們等上幾分鐘,然后點擊停止按鈕。之后,我們可以打開自帶的Health應用。你會發(fā)現(xiàn)睡眠數(shù)據(jù)已經(jīng)出現(xiàn)在界面中了。

sleep-analysis-test
sleep-analysis-test

小貼士時間

HealthKit是為開發(fā)者用來提供一個通用的平臺,通過這個平臺,我們可以輕松的共享,獲取用戶數(shù)據(jù),同時并且避免了重復或者前后矛盾的數(shù)據(jù)。在Apple審核應用規(guī)則中明確規(guī)定了,必須要清楚明確的請求獲取用戶的Health權限,如果不這么做,很可能你的應用會被拒絕上架。

如果一個應用試圖在Health應用中存入虛假的或者不正確的數(shù)據(jù),同樣會被拒絕上架。這意味著,像本教程中使用非常簡單的算法去計算不同的健康數(shù)據(jù),這樣也是不行的。你應該利用內(nèi)建的傳感器去獲取數(shù)據(jù),計算數(shù)據(jù),這樣,你獲得的數(shù)據(jù)會更加真實有效。

如果你想獲得完全的Xcode工程,你可以從這里獲取。

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容