作者:ANUSHK MITTAL,时间:2016/6/18
翻译:BigNerdCoding, 如有错误欢迎指出。原文链接

当今关于睡眠革命的话题的讨论非常热烈,人们也比以往任何时候都更加的好奇。他们关心的内容不仅有在什么时候他们睡着了,还有那些通过分析过去一段时间以来自身睡眠数据所揭示出来的睡眠趋势。随着包括硬件等技术的进步,尤其是智能手机的普及将这个看似正在不断升温的话题带到了一个全新的境界。

苹果公司提供了一种非常酷的方式来安全的与个人健康信息进行交互并且通过预装的内置Health应用将这些健康信息存储起来。通过HealthKit框架你不仅可以创建一个身体素质的应用,还可以访问到用户的睡眠分析数据。

在这篇教程中,我会对HealthKit框架做一个简介,并且演示如果使用该框架创建一个睡眠分析的简单应用。

简介

HealthKit框架提供了数据结构以便我们能够将数据存储到名为HealthKit store的加密数据库中。我们可以通过HKHealthStore类来对该加密数据库进行访问。iPhone和iWatch都有自己的HealthKit store,两者之间的健康数据会进行同步。然而,对iWatch中的老旧数据进行定时清理有助于节省iWatch的空间。HealthKitHealth应用并不存在于iPad中。

如果你想创建一个iOS或者watchOS上基于健康数据的应用话,HealthKit对你来说将是一个强大的工具。该框架被设计用来管理那些来源广泛的数据,并且基于用户的偏爱对这些来源不同的数据进行合并。应用也可以访问这些来源不同的元素数据,并自身对其进行合并处理操作。除了用于对身体的测量、体质和营养的分析,这些数据还可以用来对用户的睡眠进行分析。

在本文的剩余部分,我将会为你演示在iOS平台上如何使用HealthKit框架来保存和访问睡眠分析数据。这些方法同样适用于watchOS平台。请注意教程中的实例Xcode7上面使用Swift2.0实现的,所以在跟随我脚步之前请确保你的Xcode是7以上的版本。

在我们进行下一步之前,请先下载起始工程并将其解压。我已经在工程里面为你创建好了带有基本功能的用户界面。当你运行工程的时候,你将会看见一个计时功能的UI界面(当你按下开始按键的时候会统计时间)。

使用HealthKit框架

我们应用的目标是通过StartStop按键保持睡眠分析信息并取回该数据。为了使用HealthKit,首先你必须让你的应用获得授权。在你的app工程里面选中当前目标,然后选择capabilities并打开HealthKit功能。

下一步你需要使用下面的代码在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")
        }
    }
}

这段代码将会提示用户允许或者拒绝用户的授权请求。在completion block里面你可以对成功或者错误进行处理并且得到最终的结果。并不是所有的用户都会给予你相应的权限,你需要妥善的处理好用户拒绝的情况。

但是为了测试的目的,你必须选择允许应用获得访问设备中健康数据的的权限。

写入睡眠分析数据

首先,我们如何检索到睡眠分析数据呢?根据苹果官方的文档,每一个睡眠分析样本都有一个唯一值。为了表示用户在床上和睡觉两种状态,HealthKit使用了两个以上时间可能重叠的样本。通过比较这些样本的起始和终止时间,app可以计算出下面这些相关的统计数据:

  • 用户入睡花费的时间

  • 用户在实际睡觉时间在床上时间的占比

  • 用户醒了依然在床上的次数

  • 用户在床上和睡眠花费的总时间

简单来说,你可以通过下面的方法来将睡眠数据保存到HealthKit store

  1. 我们定义两个对应开始时间和结束时间的NSDate对象。

  2. 使用HKCategoryTypeIdentifierSleepAnalysis来创建一个HKObjectType实例

  3. 我们需要创建一个HKCategorySample类型的对象。你通常会使用类别样本来纪录这些睡眠数据。使用单个样本来表示用户在床上或者睡着了的时间段。所以我们创建一个在床上以及一个睡着了的样本,两种的时间段有重叠。

  4. 最后,我们使用HKHealthStore中的saveObject方法来保存对象。

编辑提醒:针对样本的类型,你可以查看HealthKit Constants Reference来了解。

如果你将上面的方法转化为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,endDate: self.endTime)
    
        healthStore.saveObject(object2,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中的时候调用。

读取睡眠分析数据

为了读取出睡眠分析数据,我们需要创造一个队列。首先你需要定义一个HKCategoryTypeIdentifierSleepAnalysis类别的HKObjectType对象。你可能会使用起始和结束数据作为条件来筛选位于这段时间的数据。你还需要创建一个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)
    }
}

上面的代码会查出所有的睡眠数据并按照降序的方式进行排列。然后每一个查询结果都按照:起始时间、结束时间、类型值(例如:在床上还是睡着了)的形式打印出来。我在查询中通过设置limit只取最后的30个样本。你也可以通过predicate方法选择你自定义的起始和结束时间。

App测试

在演示应用中,我使用了NSTimer来纪录点击开始按键后流失的时间。当点击开始和结束按键的时候都会创建一个NSDate对象,并且将经过的时间作为睡眠分析数据进行保存。在点击结束按键的时候可以触发调用saveSleepAnalysis()retrieveSleepAnalysis()方法取保存和查询睡眠数据。

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

在你自己的app中,你可能会改变NSDate对象并选择与之相关的起始和结束时间来保存在床上和睡觉的值。

如果你做出了修改的话,你可以允许程序并点击开始按键开始计时。让程序运行几分钟然后点击停止按键。然后你可以打开Health应用,你就可以看见睡眠数据了。

对使用HealthKit应用的一些建议

HealthKit是设计用来为app开发人员提供一个更加方便分享和访问用户数据的公共平台,并且避免了任何数据的重复和不一致的可能性。在苹果应用审核指导中详细的表明了:那些使用了HealthKit并且要求获取读写权限的应用如果没有清晰的表明的话那么很有可能会审核不过。

如果应用保存一些假的或者不正确的数据到Health应用中的话也有可能无法审核通过。这意味着,你不能想本文中那样很天真的使用一些算法去计算不同的健康数据。你应该使用内置的传感器去读取和处理那些数据和参数,从而避免计算错误数据。

完整的Xcode工程可以在这里下载得到。

通过Swift语言来使用HealthKit中的睡眠分析功能的更多相关文章

  1. HTML5 播放 RTSP 视频的实例代码

    目前大多数网络摄像头都是通过 RTSP 协议传输视频流的,但是 HTML 并不标准支持 RTSP 流。本文重点给大家介绍HTML5 播放 RTSP 视频的实例代码,需要的朋友参考下吧

  2. 利用Node实现HTML5离线存储的方法

    这篇文章主要介绍了利用Node实现HTML5离线存储的方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  3. 详解如何通过H5(浏览器/WebView/其他)唤起本地app

    这篇文章主要介绍了详解如何通过H5(浏览器/WebView/其他)唤起本地app的相关资料,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  4. H5混合开发app如何升级的方法

    本篇文章主要介绍了H5混合开发app如何升级的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  5. AmazeUI 折叠面板的实现代码

    这篇文章主要介绍了AmazeUI 折叠面板的实例代码,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  6. HTML5手指下滑弹出负一屏阻止移动端浏览器内置下拉刷新功能的实现代码

    这篇文章主要介绍了HTML5手指下滑弹出负一屏阻止移动端浏览器内置下拉刷新功能的实现代码,代码简单易懂,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧

  7. Html5 video标签视频的最佳实践

    这篇文章主要介绍了Html5 video标签视频的最佳实践,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

  8. html5唤起app的方法

    这篇文章主要介绍了html5唤起app的方法的相关资料,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  9. HTML5拍照和摄像机功能实战详解

    这篇文章主要介绍了HTML5拍照和摄像机功能实战详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  10. HTML5逐步分析实现拖放功能的方法

    这篇文章主要介绍了HTML5逐步分析实现拖放功能的方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

随机推荐

  1. Swift UITextField,UITextView,UISegmentedControl,UISwitch

    下面我们通过一个demo来简单的实现下这些控件的功能.首先,我们拖将这几个控件拖到storyboard,并关联上相应的属性和动作.如图:关联上属性和动作后,看看实现的代码:

  2. swift UISlider,UIStepper

    我们用两个label来显示slider和stepper的值.再用张图片来显示改变stepper值的效果.首先,这三个控件需要全局变量声明如下然后,我们对所有的控件做个简单的布局:最后,当slider的值改变时,我们用一个label来显示值的变化,同样,用另一个label来显示stepper值的变化,并改变图片的大小:实现效果如下:

  3. preferredFontForTextStyle字体设置之更改

    即:

  4. Swift没有异常处理,遇到功能性错误怎么办?

    本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请发送邮件至dio@foxmail.com举报,一经查实,本站将立刻删除。

  5. 字典实战和UIKit初探

    ios中数组和字典的应用Applicationschedule类别子项类别名称优先级数据包contactsentertainment接触UIKit学习用Swift调用CocoaTouchimportUIKitletcolors=[]varbackView=UIView(frame:CGRectMake(0.0,0.0,320.0,CGFloat(colors.count*50)))backView

  6. swift语言IOS8开发战记21 Core Data2

    上一话中我们简单地介绍了一些coredata的基本知识,这一话我们通过编程来实现coredata的使用。还记得我们在coredata中定义的那个Model么,上面这段代码会加载这个Model。定义完方法之后,我们对coredata的准备都已经完成了。最后强调一点,coredata并不是数据库,它只是一个框架,协助我们进行数据库操作,它并不关心我们把数据存到哪里。

  7. swift语言IOS8开发战记22 Core Data3

    上一话我们定义了与coredata有关的变量和方法,做足了准备工作,这一话我们来试试能不能成功。首先打开上一话中生成的Info类,在其中引用头文件的地方添加一个@objc,不然后面会报错,我也不知道为什么。

  8. swift实战小程序1天气预报

    在有一定swift基础的情况下,让我们来做一些小程序练练手,今天来试试做一个简单地天气预报。然后在btnpressed方法中依旧增加loadWeather方法.在loadWeather方法中加上信息的显示语句:运行一下看看效果,如图:虽然显示出来了,但是我们的text是可编辑状态的,在storyboard中勾选Editable,再次运行:大功告成,而且现在每次单击按钮,就会重新请求天气情况,大家也来试试吧。

  9. 【iOS学习01】swift ? and !  的学习

    如果不初始化就会报错。

  10. swift语言IOS8开发战记23 Core Data4

    接着我们需要把我们的Rest类变成一个被coredata管理的类,点开Rest类,作如下修改:关键字@NSManaged的作用是与实体中对应的属性通信,BinaryData对应的类型是NSData,CoreData没有布尔属性,只能用0和1来区分。进行如下操作,输入类名:建立好之后因为我们之前写的代码有些地方并不适用于coredata,所以编译器会报错,现在来一一解决。

返回
顶部