在HealthKit中用 Swift 进行睡眠分析

如今,睡眠革命逐渐成为一种时尚,跟之前相比,人们不仅想知道自己的睡眠时间,同时对用于分析他们一定时间段内睡眠状态的数据感兴趣。包括硬件技术在内的,尤其是手机技能的提升,为用户这一日益增长的需求带来了全新的希望.

HealthKit

苹果提供了一种安全、炫酷的方式来显示用户的个人健康信息,并将这些信息安全的存储在 Health 这个内置的应用中。你不仅可以使用 HealthKit 来 创建一个健身应用 ,该框架还允许你访问睡眠的详细数据。这本次教程中,我将会给大家简要的介绍 HealthKit 这个框架,并演示如何创建一个简单的睡眠分析的应用。

**简介 **


HealthKit 提供了一个名为 HealthKit store 的结构用来存储加密的数据。你可以使用HKHealthStore这个类来访问这个数据库。iPhone 和 Apple Watch 都有自己的 HealthKit store,他们之间的健康数据是同步。需要注意的是,在 Apple Watch 上老的数据会被定期的清除以节省空间。并且 ,iPad不支持HealthKit 和 Health 。

如果你想基于健康数据创建一个 iOS 或者 watchOS 应用,HealthKit 是一个非常强大的工具。它被设计的目的就是管理广泛地数据源,并且根据用户的偏好自动地合并不同来源的数据。应用程序还可以访问每一条原始数据,并且合并他们。这些数据不仅能够用于身体评估,健康状况评估以及营养状况评估,还能够用于分析睡眠质量。

接下来,我将会向你展示在 iOS 上如何利用 HealthKit 保存和访问睡眠数据。这种方法也同样适合 watchOS 上的应用。请注意本次教程使用的是 Swift 2.0 和 Xcode 7。因此,请确保你跟随此教程的时候使用的是 Xcode 7(或者以上)。

在此之前,下载最开始的工程 并解压。我已经为你创建了基本功能的用户界面。当你运行这个工程的时候,你将会看到一个定时器的 UI ,当你按下开始按钮以后就会显示计时。

** 使用 HealthKit**


我们使用这个应用的目的是使用开始和停止按钮来保存睡眠分析信息和复取数据。要使用 HealthKit,你必须给你的应用授权。也就是在你的应用中,按着 target -> capabilities -> 打开HealthKit开关 这个步骤

HealthKit-allow

接下来,你需要用下面的代码在 ViewController 类中创建一个 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")
        }
    }
}

这段代码将提示用户允许或拒绝请求的访问的权限。在闭包中,你可以对成功或者失败进行处理,并得到最终结果。用户没有必要授予你的应用所有你请求的权限。所以在你的应用中你必须妥善的处理这些错误。

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

Health-App-Permission

写入睡眠分析数据


首先,我们如何复取睡眠分析数据呢?根据苹果文档,每个睡眠分析样品只能有一个值。为了区分用户是在床上还是睡着了,HealthKit 用了两个或者两个以上的重叠时间的样本。通过比较这些样品的开始和结束时间,应用就可以计算出一些次要的统计数据:

  • 用户进入睡眠所花费的时间

  • 用户在床上的时间和实际睡眠时间的百分比

  • 用户在床上醒来的次数

  • 用户在床上和睡着的时间的总和

record_sleep_data

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

  • 1、我们需要定义两个 NSDate 的对象用于开始时间和结束时间。

  • 2、用 HKCategoryTypeIdentifierSleepAnalysis 创建一个 HKObjectType的实例。

  • 3、我们需要创建一个新的HKCategorySample类型的对象,你通常使用一类的样本来记录睡眠时间,单个的样本代表用户在床上或者在睡觉的时间段。因此,我们将会创建一个在床上和一个睡着了的重叠时间样本。

  • 4、最后,我们用 HKHealthStoresaveObject 方法来保存上述实例。

如果你想用 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 的时候上述方法将会被调用。

** 读取睡眠分析数据**


要读取睡眠分析数据,我们需要创建一个query。首先你需要用 HKCategoryTypeIdentifierSleepAnalysis 定义一个 HKObjectType类型的实例,你可能还需要一个谓词来筛选你用开始时间和结束时间复取的数据,也就是你想要检索的时间范围内的 NSDate 类型的对象。你还需要创建一个 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)
    }
}

这段代码查询了在 HealthKit 上的所有睡眠分析数据并按降序排列。然后每天结果上都带着是在床上的开始结束时间或者在睡觉的开始结束时间被打印出来。我已经设置了上限30用来检索最后记录的30个样本。你也可以用谓词的方法来选择你的自定义开始时间和结束时间。

应用测试


对于这个 demo,我已经使用 NSTimer 来显示你按下按钮之后经过的时间。当开始和结束按钮按下的时候将会创建 NSDate 的对象来保存所经过的时间作为睡眠分析数据。在停止的方法中,你可以调用 saveSleepAnalysis()retrieveSleepAnalysis方法来保存和获得睡眠数据。


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

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

一旦你做了这些改变,你可以运行这个 demo 然后开始计时。让它运行几分钟,然后点击停止按钮。然后,打开 Health 这个应用,你就可以找到你的睡眠数据。

sleep-analysis-test

一些关于 HealthKit 应用的建议


HealthKit 旨在提供一个公共平台,使应用程序开发人员能够很容易地共享和访问用户的数据,并避免任何可能的重复或不一致的数据。苹果审核指南对使用 HealthKit 有很明确的要求,如果对用户的读/写权限请求没有明确的描述就很可能导致应用程序被拒绝。

应用如果保存伪造或者错误的数据到健康应用的话也将被拒绝。这就意味着,你不能像在本次教程中睡眠分析这样天真的以你的算法计算不同的健康值。你应该尝试使用内置的传感器数据读取和操作一些参数,以避免计算错误。

关于完整的 Xcode 项目,你可以在 这里 看到。

原文出处:sing Sleep Analysis in HealthKit with Swift

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念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

推荐阅读更多精彩内容