如何使用Swift来学习HealthKit中的sleep analysis

Source

如何使用Swift来学习HealthKit中的sleep analysis

如今,有关睡眠的问题变得流行起来,用户不仅对他们什么时候入睡感兴趣,更关心的是一段时间之后,应用根据收集的数据所得出的结果。随着硬件和手机技术的发展,有关科技与睡眠的话题变的极其受关注。

苹果通过内建的Health应用,提供了一种简单酷炫的方式来安全的访问和存储用户的健康信息。你不仅可以用HealthKit来开发一个健康类应用,还可以利用framework来获取有关sleep analysis的数据。

在这个教程里,我将带你快速了解HealthKit的框架,并且演示如何开发一个简单的sleep analysis应用。

简介

HealthKit框架提供了一种结构HealthKit store,利用它你可以把信息存储在一个加密的数据库里。你可以通过HKHealthStore这个类来访问数据库。iPhone和Apple Watch分别拥有自己的HealthKit store,并且里面的数据在iPhone和Apple Watch之间是同步的。但是有一点需要注意,在Apple Watch中,为了节省空间,旧的数据是会被清除的。而iPad是不支持Health Kit和Health应用的。

你如果想开发一个iOS或者watchOS的应用,那么HealthKit是一个强大的工具。HealthKit就是被设计用来管理来自不同资源的数据,而且可以根据用户的设置来合并这些数据。应用还可以访问原始数据,并且合并他们。身体指标,健康指标以及营养指标,这些数据都可以被用来做sleep analysis。

接下来,你将会了解如何使用HealthKit框架去保存和访问iOS中的sleep analysis数据。以下的内容同样适用于watchOS。这个教程是基于Swift 2.0 和 Xcode 7. 请确保你是用Xcode 7或者以上的版本。

在这之前,下载初始工程文件并且解压缩。我已经为你创建了基本的界面。当你运行这个工程的时候,你会看到一个计时器的界面,点击开始按钮,计时器开始运行。

学习HealthKit框架

这个教程的目标是开发一个简单的应用,可以存储sleep analysis的数据,以及通过开始 & 停止按钮来获取数据。第一步,你必须获得HealthKit的许可。在你的工程文件中,选择Current Target选项,选择capabilities,并且打开对应的HealthKit。

HealthKit-allow
HealthKit-allow

下一步,你需要在ViewController中创建一个HKHealthStore实例,下面是代码:

let healthStore = HKHealthStore()

接着,我们使用创建的HKHealthStore实例来访问HealthKit store。

就像刚才提到的一样,HealthKit允许用户去选择是否其他程序可以获取他们的健康数据。所以在你访问(读/写)sleep analysis数据之前,你需要获取用户的许可。怎么做呢?第一步,导入内建的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权限,用户可以选择允许或者拒绝。在完成闭包中,你可以做更多的处理,例如获取权限成功怎么办,出现错误应该怎么办。用户有可能拒绝你的访问权限,所以你必须要在完成闭包中小心的处理这些特殊情况。

为了教程的顺利进行,你必须要选择允许选项来使应用获得你手机上的健康数据。

Health-App-Permission
Health-App-Permission

写入sleep analysis数据

首先,我们如何得到sleep analysis的数据呢?根据苹果的官方文档,每一个sleep analysis的样本只包含一个值。这个值表示了用户在床上的时间和睡眠的时间,HealthKit用了二个或者二个以上的样本,每一个样本都包含与其它样本重叠的时间。通过这些样本的开始时间和结束时间,我们能够计算出这样的一些数据:

  • 用户入睡用了多长时间
  • 用户睡眠时间与用户在床上时间的比例
  • 用户醒来后直到下床的时间
  • 用户在床上和用户睡眠的总共时间
record_sleep_data
record_sleep_data

简单来说,根据以下方法,我们能够把sleep analysis数据存入到HealKit store中。

  1. 首先根据开始时间和结束时间,定义两个NSDate对象
  2. 利用HKCategoryTypeIdentifierSleepAnalysis创建HKObjectType实例
  3. 创建一个HKCategorySample实例。每一个样本代表了用户在床上或者睡眠的时间长度。所以我们创建一个在床上的样本和睡眠的样本,这两个样本有着冲重叠的时间。
    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数据到HealthKit的时候,我们可以调用这个方法。

读取sleep analysis数据

为了能够读取sleep analysis的数据,我们需要执行一个查询操作。首先,定义一个HKObjectType类别,指明类别是HKCategoryTypeIdentifierSleepAnalysis。接下来可以用predicate去过滤得到的数据,可以根据startDateendDate这两个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,并且得到所有的sleep analysis数据,并且把这些数据按照降序排序。接下来每一个查询都以startDate和endDate的形式被打印出来。例如In Bed 或者是 Asleep。 在创建query对象时,我在limit参数里传入了30,表示我想得到最后30条记录的样本。当然了,你可以用在predicate参数中,传入你自己定义的predicate对象,这样你就可以自定义startDate和endDate了。

应用测试

在这个Demo应用中,我用了一个NSTimer来模拟真实的时间,当你按下开始按钮后,计时器会运行。两个NSDate对象在开始和结束按钮被按下时分别被创建,这样我们就可以模拟记录sleep analysis数据了。在stop方法中,你可以调用saveSleepAnalysis()retrieveSleepAnalysis()方法来存储和读取睡眠数据。

@IBAction func stop(sender: AnyObject) {

    endTime = NSDate()

    saveSleepAnalysis()

    retrieveSleepAnalysis()

    timer.invalidate()

}

在你的工程文件中,你不用完全遵循我的代码,你也可以自由的改变startDate和endDate这两个NSDate对象去存储用户在床上的时间和睡眠时间。

好了,现在你可以运行你的程序,开始计时。让我们等上几分钟,然后点击停止按钮。之后,我们可以打开自带的Health应用。你会发现睡眠数据已经出现在界面中了。

sleep-analysis-test
sleep-analysis-test

小贴士时间

HealthKit是为开发者用来提供一个通用的平台,通过这个平台,我们可以轻松的共享,获取用户数据,同时并且避免了重复或者前后矛盾的数据。在Apple审核应用规则中明确规定了,必须要清楚明确的请求获取用户的Health权限,如果不这么做,很可能你的应用会被拒绝上架。

如果一个应用试图在Health应用中存入虚假的或者不正确的数据,同样会被拒绝上架。这意味着,像本教程中使用非常简单的算法去计算不同的健康数据,这样也是不行的。你应该利用内建的传感器去获取数据,计算数据,这样,你获得的数据会更加真实有效。

如果你想获得完全的Xcode工程,你可以从这里获取。

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

推荐阅读更多精彩内容