在HeatherKit使用Swift做睡眠分析

今天,睡眠的变革是一种时尚,用户比以往任何时候都好奇要了解他们已经睡了多久,更要通过收集一些数据来分析他们的睡眠趋势。现在科技的进步特别在硬件和手机已经带入我们进入了一个全新的时代。

苹果提供了一个很酷的以安全的方式与用户的个人健康信息沟通,并通过内置的应用程序健康安全存储的信息。您不仅可以使用HealthKit建立一个健身的应用程序,该框架还允许您访问睡眠分析数据。

在本教程中,我会给你一个快速介绍HealthKit框架,并演示如何构建睡眠分析简单的应用程序。

介绍

HealthKit提供了一种被称为HealthKit存储加密的数据库结构去存储数据。你能使用HKHealthStore类去访问这个数据库。无论在iPhone上还是Apple Watch上都有他们自己的HealthKit数据存储。健康数据在iPhone上和Apple Watch是同步的。然而为了节省空间Apple Watch上的数据会被周期性的清除。HealthKit和健康APP现在还不可以在iPad上使用。

如果你想根据健康数据创建一个iOS或者watchOS应用,HealthKit是一个强大的工具。它设计的目的是为了管理广泛的数据来源,依据用户的偏好设置自动合并不同的数据来源。应用程序能够访问每一个原始的数据并合并他们。不仅对身体的测量,健身或营养,该数据也可以用于睡眠分析。

对于本文的其余部分,我将告诉你如何在iOS的上去利用HealthKit框架去访问睡眠分析数据。相同的方法也可以使用在watchOS上。请注意本教程使用Swift2.0和XCode7.请确保使用XCode7或者更高的版本。

在继续之前,下载启动项目解压。我已经为你写好了基本的用户界面。当您运行启动项目,你会看到一个计时器UI,你按下启动按钮后,标签上回显示经过的时间。

使用HealthKit框架工作

我们使用这个应用程序的目的是使用开始和暂停按钮保存睡眠数据和读取数据。使用HealthKit你必须在应用开始时候给HealthKit授权。在你的应用程序中,导航到你的当前Target ->功能并打开HealthKit。


接下来,使用下面的代码创建一个HKHealthStore实例在ViewController类中

let healthStore = HKHealthStore()

稍后我们将使用HKHealthStore实例访问HealthKit存储。

正如前面提到的,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")
        }
    }
}

此代码将提示用户允许或拒绝请求的权限。当回调完成是你可以处理成功或者失败,并获得最终结果。用户没有必要授权你的应用所有的授权。但是你必须在你的应用中妥善处理错误。

但是出于测试目的,你必须选择“允许”选项,授予应用程序权限访问设备上的健康数据。

写睡眠分析数据

首先,我们如何能读取睡眠分析数据?根据苹果的文档,每个睡眠分析样品仅仅有一个值。代表用户在床上睡了,HealthKit能够在重复的时间段中使用超过两个或者更多的数据。通过比较这些样品的开始和结束时间,应用可以计算一些次要统计:

  • 用户入睡花费的时间
  • 在床上和实际入睡的百分比
  • 用户在睡觉中醒了多少次
  • 总共在床上花费多长时间

简单地说,你按照下面的方法来分析的睡眠数据并保存到HealthKit存储中:

  • 我们需要定义两个NSDate对象来比较开始时间和介绍时间
  • 我们使用HKCategoryTypeIdentifierSleepAnalysis创建一个HKObjectType实例
  • 我们需要创建一个HKCategorySample类型的实例。您通常使用类别的样本来记录睡眠数据。个体样品代表的时间段,当用户是在床或睡着了。所以我们将创建一个在重复时间段内在床上的样本和睡着的样本。
  • 最后我们将会保存这个对象使用HKHealthStore的saveObject方法
编者注:对于样品类型,你需要查看一下[HealthKit Constants Reference](https://developer.apple.com/library/ios/documentation/HealthKit/Reference/HealthKit_Constants/index.html#//apple_ref/doc/uid/TP40014710).

如果你用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
            }
            
        })
        
    }
    
}

这个函数可以在我们需要保存用户睡眠数据的时候调用。

读取睡眠数据

为了读取用户数据,我们需要新建一个查询。你应该首先为HKCategoryTypeIdentifierSleepAnalysis定义一个HKObjectType类别。你可能还需要一个谓词去过滤这些重复数据,你可能还需要一个谓词来筛选使用开始日期和结束日期对应的NSDate对象来检索时间范围内的数据。您还需要建立一种描述排序的检索查询,选择想要的结果。

你的睡眠分析代码应该是这样的:

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所有的睡眠数据然后以降序排列。每个查询都打印出来了开始日期和结束日期的值类型。在床上或者睡觉。我已经设置了30的上限,至少读取30组样品数据。你也可以使用谓词函数去自定义选择你自己的开始日期和结束日期。

测试应用程序

对于这个演示程序,在你点击开始按钮之后我们使用NSTimer来展示已经过去的时间。NSDate对象被创建在你点击了开始按钮之后,睡眠数据被保存在你点击了结束按钮之后。在暂停的方法中你可以调用saveSleepAnalysis()和retrieveSleepAnalysis()方法去保存和获取睡眠数据。

@IBAction func stop(sender: AnyObject) {
    endTime = NSDate()
    saveSleepAnalysis()
    retrieveSleepAnalysis()
    timer.invalidate()
}

在您的应用程序,你可能要改变的NSDate对象来选择相关的开始和结束时间(可能不同),保存在床上和睡着的值。

如果你做了更改,您可以运行演示应用程序,并开始计时。让它开始运行几分钟然后点击暂停按钮。然后打开健康APP,你就会看到睡眠数据:

健康

HealthKit应用的建议

HealthKit能够很轻松地为开发人员提供一个共享的平台和访问用户的数据,避免数据中的任何可能的重复或不一致。苹果的审核指导使用HealthKit并要求读/写权限,非常具体的表明可能导致被拒绝的应用程序。

在健康应用程序中保存假的或者不正确的数据也可能会被拒绝。这意味着你不能像本教程这样把你的健康分析算法写的这么简单。你应该尝试使用内置的传感器数据读取和处理任何参数,以避免错误的计算数据。

完整的项目你可以从这里下载.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容