HealthKit框架學(xué)習(xí)
本文結(jié)構(gòu)
- 簡(jiǎn)介
- 用戶數(shù)據(jù)安全及隱私
- HealthKit框架介紹
- HealthKit使用
- 總結(jié)
簡(jiǎn)介
HealthKit
是Apple公司在推出iOS 8 系統(tǒng)時(shí)一塊推出的關(guān)于健康信息的框架拦键。如果iPhone手機(jī)系統(tǒng)升級(jí)到iOS8之后就會(huì)發(fā)現(xiàn)多了一個(gè)健康-app
,這就是Apple提供的一個(gè)記錄用戶健康信息的app,可以用它來分享健康和健身數(shù)據(jù)芒涡。還可以指定數(shù)據(jù)的來源鸥跟,比如我們自己創(chuàng)建一個(gè)app,在我們的app中使用了HealthKit
框架之后只要經(jīng)過用戶的認(rèn)證奢啥,就可以在我們的app之中給健康
分享數(shù)據(jù)或者從健康
中獲取數(shù)據(jù)。
HealthKit
可以與健身設(shè)備一起工作序攘,iPhone手機(jī)自身可以監(jiān)控步數(shù)信息摇予,會(huì)自動(dòng)導(dǎo)入步數(shù)信息。但是其他信息或者設(shè)備需要配套的應(yīng)該才能獲取到數(shù)據(jù)并導(dǎo)入到HealthKit
中并在健康
中顯示灵奖。
HealthKit
不能再iPad中使用,而且它也不支持?jǐn)U展搬泥。
用戶數(shù)據(jù)安全及隱私
由于用戶的健康信息可能是敏感的桑寨,所以這些用戶信息不能讓開發(fā)者很隨便的獲取到伏尼。每條信息的讀寫都需要用戶去選擇是否同意忿檩,比如用戶可以同意你獲取到用戶的身高體重,但是不同意讀寫生殖健康等其他用戶不愿意公開的信息爆阶。為了防止信息泄露燥透,我們是不知道用戶是否禁止了某條信息是否被用戶禁止讀取的沙咏。簡(jiǎn)單的說,如果獲取不到某條信息班套,就代表沒有這條信息肢藐。
關(guān)于更多的關(guān)于隱私的信息,可以參考隱私
HealthKit框架介紹
HealthKit
在各個(gè)應(yīng)用之間提供了一種有意義的方式共享數(shù)據(jù)吱韭。因此吆豹,我們必須使用HealthKit
框架提供的數(shù)據(jù)類型和單位。這保證了數(shù)據(jù)存在的真正意義理盆,我們不能自定義數(shù)據(jù)類型及單位痘煤。框架使用了子類化猿规,例如HKObject
和HKObjectType
抽象類擁有很多有平行關(guān)系的子類衷快,當(dāng)使用Object
或者ObjectType
的時(shí)候,必須確保使用正確的子類姨俩。
在HealthKit
中能夠存儲(chǔ)的類都是HKObject
的子類蘸拔,大部分HKObject
的子類都是不可變的。每個(gè)對(duì)象都有下面的屬性:
- UUID:每個(gè)對(duì)象的標(biāo)識(shí)符
- Source:數(shù)據(jù)的來源环葵,來源可以是
HealthKit
的健康app,也可以是我們自己創(chuàng)建的app调窍。當(dāng)一個(gè)對(duì)象存儲(chǔ)到HealthKit
中時(shí)會(huì)設(shè)置其來源。只有從HealthKit
中獲取到的數(shù)據(jù)的來源才有效张遭。 - Metadata:一個(gè)包含該對(duì)象額外信息的字典陨晶,元數(shù)據(jù)包含預(yù)定義的key和自定義的key,預(yù)定義的key用來幫助我們?cè)趹?yīng)用間共享數(shù)據(jù),而自定義的key用來擴(kuò)展HealthKit帝璧,為對(duì)象添加針對(duì)應(yīng)用的數(shù)據(jù)先誉。
HealthKit
的對(duì)象主要分為特征和樣本。特征對(duì)象代表用戶的基本不變的數(shù)據(jù)的烁,包括用戶的生日褐耳、血型和性別等。我們創(chuàng)建的app不能修改這些信息渴庆,只能讓用戶在健康
中去修改或者添加個(gè)人特征信息铃芦。
樣本對(duì)象代表某個(gè)特定時(shí)間的數(shù)據(jù),所有的樣本類型的對(duì)象都是HKSample
的子類襟雷。它們都有下面的特性:
- Type :樣本類型刃滓,例如:睡眠分享、步行距離耸弄、心率樣本等
- StartDate:樣本開始時(shí)間
- EndDate:樣本結(jié)束時(shí)間咧虎。如果是某一個(gè)時(shí)間的樣本,則開始于結(jié)束時(shí)間相同计呈,如果是某個(gè)時(shí)間段的樣本砰诵,則結(jié)束時(shí)間在開始時(shí)間的后面征唬。
樣本類型又可以分為四個(gè)類型:
- 類別樣本(
HKCategorySample
):在iOS 8 中,只有睡眠分析這一個(gè)類別樣本茁彭。代表有限種類的樣本. - 數(shù)量樣本(
HKQuantitySample
):這種樣本代表存儲(chǔ)數(shù)據(jù)的樣本总寒,比如步數(shù)、距離理肺、用戶的體溫等摄闸。它是HealthKit
中最常見的數(shù)據(jù)類型。 - 關(guān)系樣本(
HKCorrelation
):代表復(fù)合數(shù)據(jù)妹萨,包括一個(gè)或者多個(gè)樣本贪薪。在iOS 8 中,用correlation
代表食物和血壓眠副。在創(chuàng)建食物或血壓時(shí)画切,需要用correlation
。 - 訓(xùn)練活動(dòng)(
HKWorkout
):代表某種活動(dòng)囱怕,比如走霍弹、跑步等。包含有開始時(shí)間娃弓、結(jié)束時(shí)間典格、運(yùn)動(dòng)類型、消耗能量台丛、運(yùn)動(dòng)距離等屬性耍缴。還可以為workout
關(guān)聯(lián)許多詳細(xì)的樣本。不像correlation
挽霉,這些樣本不包含在workout
中防嗡,但是可以通過workout
獲取到。
再介紹一個(gè)HealthKit中經(jīng)常用到的一些類侠坎。
HKSamle
每個(gè)HkSample
的子類都有對(duì)應(yīng)的便利方法創(chuàng)建對(duì)應(yīng)的對(duì)象蚁趁。比如:
對(duì)于數(shù)量樣本,需要?jiǎng)?chuàng)建HKQuantity
類的實(shí)例实胸。而且數(shù)量的單位和類型標(biāo)識(shí)符文檔中描述的可用單位要相同他嫡。例如:HKQuantityTypeIdentifierHeight
文檔中說明它使用長(zhǎng)度單位,因此庐完,你的數(shù)量必須使用厘米钢属、米、英尺门躯、英寸或者其他長(zhǎng)度單位淆党。
對(duì)應(yīng)類別樣本,需要?jiǎng)?chuàng)建HKCategorySample
的實(shí)例。它的值必須和類型標(biāo)識(shí)符文檔中描述的枚舉值相關(guān)宁否。例如窒升, HKCategoryTypeIdentifierSleepAnalysi
s 文檔中說明它使用的枚舉值缀遍。因此你在創(chuàng)建樣本時(shí)必須從這個(gè)枚舉中傳遞一個(gè)值慕匠。
同樣,你必須先創(chuàng)建correlation包含的所有樣本域醇。correlation的類型標(biāo)識(shí)符描述了它可以包含的類型和對(duì)象的數(shù)量台谊。不要把被包含的對(duì)象存進(jìn)HealthKit。它們是以correlation的一部分存儲(chǔ)的譬挚。
對(duì)于訓(xùn)練活動(dòng)樣本锅铅,首先,創(chuàng)建 HKWorkoutType
實(shí)例并不需要指定類型標(biāo)識(shí)符减宣。所有的workout都是用同樣的類型標(biāo)識(shí)符盐须。第二,對(duì)于每個(gè)workout
你都需要提供一個(gè) HKWorkoutActivityType
值漆腌。這個(gè)值定義了workout
中執(zhí)行的活動(dòng)的類型贼邓。最后,當(dāng)workout
保存到HealthKit
后闷尿,你可以給workout
關(guān)聯(lián)額外的樣本塑径。這些樣本提供了workout
的詳細(xì)信息。
HKQuery
HealthKit提供了許多查詢讀取數(shù)據(jù)的方法:
直接方法查詢填具。對(duì)于特征樣本统舀,可以直接查詢獲取到,這些方法只能查詢特征樣本劳景。更多信息: HKHealthStore Class Reference
樣本查詢誉简。這是使用最多的查詢。使用樣本查詢可以查詢?cè)贖ealthKit中任意的數(shù)據(jù)盟广。而且可以對(duì)結(jié)果進(jìn)行排序等描融。更多信息:HKSampleQuery Class Reference
觀察者查詢。這是一個(gè)長(zhǎng)時(shí)間運(yùn)行的查詢衡蚂,它會(huì)檢測(cè)HealthKit存儲(chǔ)窿克,并在匹配到的樣本發(fā)生變化時(shí)通知你。如果當(dāng)存儲(chǔ)發(fā)生變化時(shí)你想得到通知毛甲,就使用觀察者查詢年叮。更多信息:HKObserverQuery Class Reference
錨定對(duì)象查詢。用這種查詢來搜索添加進(jìn)存儲(chǔ)的項(xiàng)玻募。當(dāng)錨定查詢第一次執(zhí)行時(shí)只损,會(huì)返回存儲(chǔ)中所有匹配的樣本。在接下來的執(zhí)行中,只會(huì)返回上一次執(zhí)行之后添加的項(xiàng)目跃惫。通常叮叹,錨定對(duì)象查詢會(huì)和觀察者查詢一起使用。觀察者查詢告訴你某些項(xiàng)目發(fā)生了變化爆存,而錨定對(duì)象查詢來決定有哪些(如果有的話)項(xiàng)目被添加進(jìn)了存儲(chǔ)蛉顽。更多信息:HKAnchoredObjectQuery Class Reference
統(tǒng)計(jì)查詢。使用這種查詢來在一系列匹配的樣本中執(zhí)行統(tǒng)計(jì)運(yùn)算先较。你可以使用統(tǒng)計(jì)查詢來計(jì)算樣本的總和携冤、最小值、最大值或平均值闲勺。更多信息: HKStatisticsQuery Class Reference
統(tǒng)計(jì)集合查詢曾棕。使用這種查詢來在一系列長(zhǎng)度固定的時(shí)間間隔中執(zhí)行多次統(tǒng)計(jì)查詢。通常使用這種查詢來生成圖表菜循。查詢提供了一些簡(jiǎn)單的方法來計(jì)算某些值翘地,例如,每天消耗的總熱量或者每5分鐘行走的步數(shù)癌幕。統(tǒng)計(jì)集合查詢是長(zhǎng)時(shí)間運(yùn)行的衙耕。查詢可以返回當(dāng)前的統(tǒng)計(jì)集合,也可以監(jiān)測(cè)HealthKit存儲(chǔ)序芦,并對(duì)更新做出響應(yīng)臭杰。更多信息,參見 HKStatisticsCollectionQuery Class Reference谚中。
Correlation查詢渴杆。使用這種查詢來在correlation查找數(shù)據(jù)。這種查詢可以為correlation中每個(gè)樣本類型包含獨(dú)立的謂詞宪塔。如果你只是想匹配correlation類型磁奖,那么請(qǐng)使用樣本查詢。更多信息某筐,參見 HKCorrelation Class Reference比搭。
來源查詢。使用這種查詢來查找HealthKit存儲(chǔ)中的匹配數(shù)據(jù)的來源(應(yīng)用和設(shè)備)南誊。來源查詢會(huì)列出儲(chǔ)存的特定樣本類型的所有來源身诺。更多信息,參見HKSourceQuery Class Reference抄囚。
HKUnit
這個(gè)類代表要查詢的數(shù)據(jù)的單位的類霉赡,比如體重的單位,可以為kg幔托、lbs等穴亏。這個(gè)類為不同的數(shù)據(jù)類型提供了不同的單位方法蜂挪。一般在創(chuàng)建前面介紹的樣本類型的時(shí)候,都需要這個(gè)類為樣本添加對(duì)應(yīng)的單位嗓化。而且提供了一些數(shù)學(xué)運(yùn)算棠涮,比如千米、米刺覆、厘米等之間的轉(zhuǎn)換严肪。
在某些場(chǎng)合,你可以使用格式化器來本地化數(shù)量隅津。iOS8提供了提供了新的格式化器來處理長(zhǎng)度(NSLengthFormatter
)诬垂、質(zhì)量(NSMassFormatter
)和能量(NSEnergyFormatter
)劲室。對(duì)于其他的數(shù)量伦仍,你需要自己來?yè)Q算單位和本地化數(shù)據(jù)。
HKHeathStore
HealthKit的核心就是它很洋,它代表HealthKit的數(shù)據(jù)庫(kù)充蓝,使用它就可以從數(shù)據(jù)庫(kù)中讀取數(shù)據(jù)。比較重要的方法:
- isHealthDataAvailable:判斷當(dāng)前設(shè)置是否支持HealthKit
- requestAuthorizationToShareTypes(typesToShare: Set<HKSampleType>?, readTypes typesToRead: Set<HKObjectType>?, completion: (Bool, NSError?) -> Void): 向用戶請(qǐng)求同意讀寫某些數(shù)據(jù)
- saveObject(object: HKObject, withCompletion completion: (Bool, NSError?) -> Void) :向數(shù)據(jù)庫(kù)中添加數(shù)據(jù)
- executeQuery(query: HKQuery) :執(zhí)行查詢喉磁,即上面介紹的幾種查詢方法谓苟。
HealthKit使用
在使用HealthKit
之前,必須要執(zhí)行下列步驟:
打開
HealthKit
,在Target欄中协怒,打開Capabilities
菜單涝焙,將HealthKit
這一項(xiàng)的開關(guān)設(shè)為ON的狀態(tài)。-
創(chuàng)建
HeathManager.Swift
文件孕暇,并導(dǎo)入`import HealthKit`
HealthKit
的核心是HeathStore
仑撞,創(chuàng)建func authorizeHealthKit(completion:((success:Bool,error:NSError!)->Void)!){}
然后調(diào)用在這個(gè)方法中調(diào)用
isHealthDataAvailable
判斷當(dāng)前設(shè)備是否支持HealthKit
//判斷當(dāng)前設(shè)備是否支持 if !HKHealthStore.isHealthDataAvailable(){ let error = NSError(domain: "", code: 2, userInfo: [NSLocalizedDescriptionKey:"HealthKit is not available in this Device"]) if completion != nil { completion(success: false, error: error) } }
,最后在上面的方法中妖滔,設(shè)置要讀寫的數(shù)據(jù)類型隧哮。
-
為你的應(yīng)用實(shí)例化一個(gè) HKHealthStore 對(duì)象。每個(gè)應(yīng)用只需要一個(gè)HealthKit存儲(chǔ)實(shí)例座舍。這個(gè)存儲(chǔ)實(shí)例就是你和HealthKit數(shù)據(jù)庫(kù)交互的主要接口沮翔。
let hkHealthStore = HKHealthStore()
-
使用
requestAuthorizationToShareTypes:readTypes:completion:
來認(rèn)證請(qǐng)求從HealthKit獲取數(shù)據(jù)的權(quán)限。//請(qǐng)求連接 hkHealthStore.requestAuthorizationToShareTypes(healthKitTypesToWrite as? Set<HKSampleType>, readTypes: healthKitTypesToRead as? Set<HKObjectType>) { (success, error) -> Void in if completion != nil{ completion(success:success,error:error) } return }
如果當(dāng)前設(shè)備支持HealthKit的時(shí)候曲秉,這樣就會(huì)彈出一個(gè)請(qǐng)求界面采蚀,讓用戶選擇是否同意你能夠獲取到你要請(qǐng)求的數(shù)據(jù)。
獲取特征信息
我們首先創(chuàng)建了ProfileViewController.swift
,并用IB創(chuàng)建一個(gè)請(qǐng)求個(gè)人信息的界面
然后在HeathManager.Swift
文件中添加請(qǐng)求個(gè)人信息的方法承二。
對(duì)于請(qǐng)求特征信息榆鼠,前提上用戶通過健康
添加了出生日期、性別矢洲、血型等特征信息
func readProfile()->(age:Int?,biologicalsex:HKBiologicalSexObject?,bloodType:HKBloodTypeObject?){
//請(qǐng)求年齡
var age:Int?
let birthDay:NSDate;
do {
birthDay = try hkHealthStore.dateOfBirth()
let today = NSDate()
let diff = NSCalendar.currentCalendar().components(.Year, fromDate: birthDay, toDate: today, options: NSCalendarOptions(rawValue: 0))
age = diff.year
}catch {
}
//請(qǐng)求性別
var biologicalSex
:HKBiologicalSexObject?
do {
biologicalSex = try hkHealthStore.biologicalSex()
}catch {
}
//請(qǐng)求血型
var hkbloodType:HKBloodTypeObject?
do {
hkbloodType = try hkHealthStore.bloodType()
}catch{
}
return (age,biologicalSex,hkbloodType)
}
請(qǐng)求體重璧眠、身高、BMI的時(shí)候,創(chuàng)建另外的方法责静。
func fetchMostRecentSample(sample:HKSampleType,competion:((HKSample!,NSError!)->Void)!){
//1.創(chuàng)建謂詞
let past = NSDate.distantPast()
let now = NSDate()
let mostRecentPredicate = HKQuery.predicateForSamplesWithStartDate(past, endDate: now, options: .None)
//2.創(chuàng)建返回結(jié)果排序的描述袁滥,是降序還是升序的,因?yàn)橹恍枰粋€(gè)結(jié)果灾螃,就設(shè)定限制為1個(gè)
let sortDescrptor = NSSortDescriptor(key:HKSampleSortIdentifierStartDate , ascending: false)
let limit = 1
//3.創(chuàng)建HKSampleQuery對(duì)象题翻,
let sampleQuery = HKSampleQuery(sampleType: sample, predicate: mostRecentPredicate, limit: limit, sortDescriptors: [sortDescrptor]) { (sampleQuery, results, error) -> Void in
if let queryError = error {
competion(nil,queryError)
return
}
let mostRecentSample = results?.first
if competion != nil{
competion(mostRecentSample,nil)
}
}
//4.執(zhí)行查詢
self.hkHealthStore.executeQuery(sampleQuery)
}
獲取之后在之前創(chuàng)建的ProfileViewController.swift
文件中獲取這些信息,并更新UI腰鬼。
對(duì)應(yīng)特征信息嵌赠,可以直接調(diào)用查詢方法,并更新
let profile = healthManager?.readProfile()
self.healthStore = HKHealthStore()
ageLabel.text = profile?.age == nil ? kUnKnowString:String(profile!.age!)
sexLabel.text = biologicSexLiteral(profile?.biologicalsex?.biologicalSex)
bloodTypeLabel.text = bloodTypeLiteral(profile?.bloodType?.bloodType)
這里面創(chuàng)建了兩個(gè)工具方法biologicSexLiteral
和bloodTypeLiteral
來修改查詢的結(jié)果為我們想要的樣子并顯示在界面上熄赡。
對(duì)于體重和身高姜挺,需要?jiǎng)?chuàng)建樣本查詢
/**
獲取并更新體重
*/
func updateWeight(){
let weightSampleType = HKSampleType.quantityTypeForIdentifier(HKQuantityTypeIdentifierBodyMass)
self.healthManager?.fetchMostRecentSample(weightSampleType!, competion: { (mostRecentSample, error) -> Void in
if error != nil {
return
}
var weightString = self.kUnKnowString
self.weight = mostRecentSample as? HKQuantitySample
//根據(jù)我們想要的數(shù)據(jù)類型單位獲取對(duì)應(yīng)的結(jié)果
if let kilograms = self.weight?.quantity.doubleValueForUnit(HKUnit.gramUnitWithMetricPrefix(HKMetricPrefix.Kilo)){
//體重格式化
let weightFommater = NSMassFormatter()
weightFommater.forPersonMassUse = true
weightString = weightFommater.stringFromKilograms(kilograms)
}
//因?yàn)檫@個(gè)查詢默認(rèn)是異步查詢的,所以需要在主線程更新UI
dispatch_async(dispatch_get_main_queue()) { () -> Void in
self.weightLabel.text = weightString
self.updateBMILabel()
}
})
}
/**
獲取并更新身高
*/
func updateHeight(){
//設(shè)置要查找的類型彼硫,根據(jù)標(biāo)識(shí)符
let heightSampleType = HKSampleType.quantityTypeForIdentifier(HKQuantityTypeIdentifierHeight)
//獲取身高樣本
self.healthManager?.fetchMostRecentSample(heightSampleType!, competion: { (heightSample, error) -> Void in
if error != nil {
return
}
var heightStr = self.kUnKnowString
self.height = heightSample as? HKQuantitySample
//根據(jù)我們想要的數(shù)據(jù)類型單位獲取對(duì)應(yīng)的結(jié)果
if let kilograms = self.height?.quantity.doubleValueForUnit(HKUnit.meterUnit()){
heightStr = String(format: "%.2f", kilograms) + "m"
}
//因?yàn)檫@個(gè)查詢默認(rèn)是異步查詢的炊豪,所以需要在主線程更新UI
dispatch_async(dispatch_get_main_queue()) { () -> Void in
self.heightLabel.text = heightStr
self.updateBMILabel()
}
})
}
對(duì)應(yīng)BMI,它代表人的身體質(zhì)量指數(shù),它的計(jì)算方式是:體重/(身高*身高)拧篮。因此它可以這樣獲得
/**
獲取并設(shè)置BMI:
*/
func updateBMILabel(){
//根據(jù)我們想要的數(shù)據(jù)類型單位獲取對(duì)應(yīng)的結(jié)果
let weight = self.weight?.quantity.doubleValueForUnit(HKUnit.gramUnitWithMetricPrefix(HKMetricPrefix.Kilo))
let height = self.height?.quantity.doubleValueForUnit(HKUnit.meterUnit())
var bmiValue = 0.0
if height == 0{
return
}
dispatch_async(dispatch_get_main_queue()) { () -> Void in
bmiValue = (weight!)/(height! * height!)
self.BMILabel.text = String(format: "%.02f", bmiValue)
}
}
添加BMI到HeathStore
在下面的方法中添加一個(gè)alertView
讓用戶輸入BMI值词渤,然后點(diǎn)擊確認(rèn)按鈕之后添加到HeathStore
中
@IBAction func addBMIData2HealthStore(sender: AnyObject) {
let alertView = UIAlertController(title: "輸入BMI值", message: nil, preferredStyle: .Alert)
alertView.addTextFieldWithConfigurationHandler { (textField) -> Void in
textField.keyboardType = .NumberPad
}
let action = UIAlertAction(title: "添加", style: .Default) { (action) -> Void in
var value:Double?
if let text = alertView.textFields?.first?.text {
if text.characters.count > 0 {
value = Double(text)
self.saveBMI2HealthStore(value!)
}
}
}
alertView.addAction(action)
self .presentViewController(alertView, animated: true, completion: nil)
}
//保存BMI到HealthKitStore中
func saveBMI2HealthStore(height:Double){
//BMI的類型
let BMIType = HKQuantityType.quantityTypeForIdentifier(HKQuantityTypeIdentifierBodyMassIndex)
//根據(jù)標(biāo)識(shí)符對(duì)應(yīng)的單位創(chuàng)建BMI的數(shù)量對(duì)象
let BMIQuantity = HKQuantity(unit: HKUnit.countUnit(), doubleValue: height)
let now = NSDate()
//根據(jù)起止時(shí)間以及上面創(chuàng)建的創(chuàng)建HKQuantity對(duì)象創(chuàng)建數(shù)量樣本
let BMISample = HKQuantitySample(type: BMIType!, quantity: BMIQuantity, startDate: now, endDate: now)
//保存數(shù)量樣本到healthStore中
self.healthStore?.saveObject(BMISample, withCompletion: { (success, error) -> Void in
if success {
print("添加成功")
self.updateWeight()
}
if (error != nil) {
print("添加失敗")
}
})
}
如果添加成功,你就可以去手機(jī)上的健康
查找BMI串绩,就可以看到我們剛才添加的BMI值缺虐,而且它的來源是我們創(chuàng)建的app。
獲取HKWorkout
創(chuàng)建一個(gè)WorkOutsViewController.swift
文件礁凡,并在SB中拖對(duì)應(yīng)的IB文件高氮,界面如下
然后在在HeathManager.Swift
文件中添加請(qǐng)求workout的方法
/**
獲取workoutData
*/
func fetchWorkOutsData(completion:([AnyObject]!,NSError!)->Void){
let workOutsSampleType = HKSampleType.workoutType()
let workOutsPredicate = HKQuery.predicateForWorkoutsWithWorkoutActivityType(.Running)
let sortDescrptor = NSSortDescriptor(key:HKSampleSortIdentifierStartDate , ascending: false)
let workOutsQuery = HKSampleQuery(sampleType: workOutsSampleType, predicate: workOutsPredicate, limit: 0, sortDescriptors: [sortDescrptor]) { (workoutsQuery, results, error) -> Void in
if (error != nil){
print("獲取失敗")
return
}
if results != nil{
completion(results!,nil)
}
}
self.hkHealthStore.executeQuery(workOutsQuery)
}
然后在WorkOutsViewController.swift
文件的viewWillAppear()
方法中請(qǐng)求workout
self.healthManager?.fetchWorkOutsData({ (results, error) -> Void in
if error != nil{
print("獲取失敗")
}else{
self.workOuts = results as! [HKWorkout]
}
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.tableView.reloadData()
});
})
最后在tableView顯示如下
保存HKWorkout
在上面的界面的NavgationBar的rightBarItem向下再拖一個(gè)控制器,并添加對(duì)應(yīng)的文件AddWorkoutsViewController.swift
把篓,并在IB中設(shè)置界面信息如下
然后在 AddWorkoutsViewController.swift
復(fù)寫 tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
,針對(duì)點(diǎn)擊不同的cell纫溃,執(zhí)行不同的方法。即讓用戶輸入點(diǎn)擊的cell對(duì)應(yīng)的輸入方式韧掩,比如時(shí)間就是時(shí)間選擇器紊浩。距離就是一個(gè)警示框加一個(gè)文本框等。
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
tableView.deselectRowAtIndexPath(indexPath, animated: true)
self.tableView.tableFooterView = UIView()
switch indexPath.row{
case 0:
self.setupPickerView()
case 1,2:
self.setupDatePickerView(indexPath.row)
case 3,4:
self.setupAlertView(indexPath.row)
default:
break
}
}
這里面對(duì)應(yīng)的選擇的方法就不一一介紹了疗锐,就是幾個(gè)普通的view的添加坊谁。添加完所有的信息之后就可以點(diǎn)擊done
保存信息,方法如下:
@IBAction func addWorkOut(sender: AnyObject) {
self.heathStore = HKHealthStore()
//獲取距離和能量的數(shù)值
let distanceValue = Double(self.distanceLabel.text!)
let energyValue = Double(self.energyLabel.text!)
//根據(jù)上面的數(shù)值創(chuàng)建對(duì)應(yīng)的HKQuantity對(duì)象
let distance = HKQuantity(unit: HKUnit.mileUnit(), doubleValue: distanceValue!)
let energy = HKQuantity(unit: HKUnit.calorieUnit(), doubleValue: energyValue!)
let endDate = self.dateFommater?.dateFromString(self.endDateLabel.text!)
let startDate = self.dateFommater?.dateFromString(self.startDateLabel.text!)
//這里我默認(rèn)設(shè)置成running了滑臊】谏郑可以根據(jù)具體的類型再進(jìn)行設(shè)置。
//創(chuàng)建HKWorkout對(duì)象雇卷。
let workout = HKWorkout(activityType: .Running, startDate: startDate!, endDate: endDate!, workoutEvents: nil, totalEnergyBurned: energy, totalDistance: distance, metadata: nil)
//保存上面創(chuàng)建的HKWorkout對(duì)象
self.heathStore?.saveObject(workout, withCompletion: { (success, error) -> Void in
if error != nil{
print("添加錯(cuò)誤")
return
}
if success{
print("添加成功")
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.dismissViewControllerAnimated(true, completion: nil)
})
}
})
}
如果上面都執(zhí)行成功鬓椭,AddWorkoutsViewController.swift
就會(huì)模態(tài)消失颠猴,然后在上面的一個(gè)頁(yè)面``WorkOutsViewController.swift就會(huì)在tableView的最上層顯示出我們剛才添加成功的
HKWorkout`
總結(jié)
在本人過完春節(jié)回到公司上班之后經(jīng)理問我健康
app里面的信息能不能獲取到。之前只是簡(jiǎn)單了解了這個(gè)框架小染,但是里面的具體結(jié)構(gòu)體系并不了解翘瓮。就趁著項(xiàng)目不忙,抽空把HealthKit學(xué)習(xí)了解了一下裤翩。本文的demo也采用了之前自學(xué)的Swift簡(jiǎn)單的實(shí)現(xiàn)了一下(屬于Switer新手)资盅。可能會(huì)有錯(cuò)誤或不準(zhǔn)確的地方踊赠,如果你看到了呵扛,可以給我聯(lián)系ls_xyq@126.com,我會(huì)及時(shí)更改的筐带。寫這篇文章一是對(duì)HealthKit的學(xué)習(xí)的一個(gè)練習(xí)今穿,在這也是給以后會(huì)用到的童鞋一個(gè)可以參考的東西。
HealthKit不只是上面的這些內(nèi)容烫堤,但是能把上面的這些問題搞定荣赶,我覺得針對(duì)HealthKit的體系會(huì)有一個(gè)清楚的認(rèn)識(shí)凤价,學(xué)習(xí)HealthKit更深層次的內(nèi)容會(huì)有很大的幫助鸽斟。
本文的demo已經(jīng)放到github上面,需要的同學(xué)可以下載看看利诺。
本文參考文章: