V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
爱意满满的作品展示区。
liuli12
V2EX  ›  分享创造

计步神器·StepRecorder( iOS)开发教程

  •  
  •   liuli12 · 2015-08-20 15:20:29 +08:00 · 4563 次点击
    这是一个创建于 3376 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我们团队最近利用业余时间用 swift 语言练手做的一个小项目,旨在帮助家人记录锻炼数据,家里老人用的是老款计步器,没办法把数据同步到“ Health ”里。

    先上最终的效果图:

    http://ww3.sinaimg.cn/bmiddle/8cd0eb7fgw1ev9340gmerj21kw0xjahf.jpg

    界面和功能都比较简单,就是输入计步器上显示的步数, APP 会自动同步到“ Health ”里。据说也可以被 “微信运动“读取。

    之前小范围给朋友测试的时候,被朋友们恶作剧用来刷榜发小广告,也是醉了。

    http://ww1.sinaimg.cn/bmiddle/8cd0eb7fgw1ev9340y5saj20zc0kogpm.jpg

    感兴趣的可以测试下“微信运动“的步数极限,但还是希望大家正确地使用这个工具。

    下面简单介绍下开发流程。

    项目设置

    创建项目,选择: Tabbed based Application ,项目的语言中选择 Swift:
    http://ww2.sinaimg.cn/bmiddle/8cd0eb7fgw1ev93cvm7f0j208w00pdfn.jpg

    打开项目后,先删除一些多余文件
    (比如 FirstViewController.swift , SecondViewController.swift ...)。

    打开 storyboard 看到之中有一个 Tab Bar Controller ,这是程序的根视图控制器,右键点击控制器就能看到它绑定的其它视图控制器。

    如果用代码的方式初始化 UI ,可以新建一个 HHRootViewController 类来绑定根视图控制器。

    HealthKit 的实现

    首先需要有 apple 的开发者账号(可以参考网上的注册教程),打开 HealthKit Capabilities ,才能在 iOS 的健康 app 中添加数据或者读取信息:

    http://ww3.sinaimg.cn/bmiddle/8cd0eb7fgw1ev93f59ef8j20k003h74j.jpg

    接下来写一个 HealthManager 类用来处理所有项目中涉及到和 HealthKit 相关的东西。 Let healthKitStore:HKHealthStore = HKHealthStore () 由于苹果的隐私政策,先申请权限,这个变量的调用方法可以获取健康信息和读取信息

    申请权限

    func authorizeHealthKit (completion: ((success:Bool, error:NSError!) -> Void )!)
    { //1
    let healthKitTypesToWrite: Set = [
    HKObjectType.quantityTypeForIdentifier (HKQuantityTypeIdentifierStepCount ),
    ]
    //2
    if !HKHealthStore.isHealthDataAvailable () { let error = NSError (domain: "com.hihex.healthkit", code: 2, userInfo:
    [NSLocalizedDescriptionKey:"HealthKit is not available in this Device"])
    if completion != nil {
    completion (success:false, error:error )
    } return;
    }
    //3
    healthKitStore.requestAuthorizationToShareTypes (healthKitTypesToWrite, readTypes: nil ) { (success, error ) -> Void in
    if completion != nil {
    completion (success:success,error:error ) }
    }
    }

    写上需要申请的权限集合,因为 app 内读取自己写入的数据不需要读取的权限所以就不申请读取的权限。

    检查设备是否能获取到健康的信息,因为有些机型如 iPad 等并不能支持 HealthKit 。

    申请权限,因为传入的是一个块你可以根据处理的结果进行 UI 上的交互。

    HealthKit 支持的活动的类型有 70 多种,可以在 HKWorkoutActivityType 里查看,有兴趣可以自己看看。

    保存运动样本

    func saveStepsSample ( steps: Double, endDate: NSDate , duration :Int, completion: ( (Bool, NSError!) -

    Void )!) { //1
    let sampleType = HKQuantityType.quantityTypeForIdentifier (HKQuantityTypeIdentifierStepCount )
    let stepsQuantity = HKQuantity (unit: HKUnit.countUnit (), doubleValue: steps ) let startDate = endDate.dateByAddingTimeInterval (0 - 60 * Double (duration ))
    //2 let stepsSample = HKQuantitySample (type:
    HKQuantityType.quantityTypeForIdentifier (HKQuantityTypeIdentifierStepCount ), quantity: stepsQuantity,
    startDate: startDate, endDate: endDate )
    //3
    self.healthKitStore.saveObject (stepsSample, withCompletion: { (success, error ) -> Void in
    completion (success,error )
    })
    }

    在一个运动的样本中,先把各项要使用的数据初始化:运动样本的类型、计算的单位、开始以及结束时间、生成运动的样本、 在 HealthKit 中保存样本。

    读取运动样本

    func readStepsWorksout (limit :Int,completion: (([AnyObject]!, NSError!) -> Void )!) {
    //1
    let sampleType = HKQuantityType.quantityTypeForIdentifier (HKQuantityTypeIdentifierStepCount ) let sortDescriptor = NSSortDescriptor (key:HKSampleSortIdentifierStartDate, ascending: false )
    let predicate = HKQuery.predicateForObjectsFromSource (HKSource.defaultSource ())
    //2
    let sampleQuery = HKSampleQuery (sampleType: sampleType, predicate: predicate, limit: limit,
    sortDescriptors: [sortDescriptor])
    { (sampleQuery, results, error ) -> Void in
    if let queryError = error {
    println ( "There was an error while reading the samples: \
    (queryError.localizedDescription )")
    }
    completion (results,error )
    }
    healthKitStore.executeQuery (sampleQuery ) }

    为需要查询的条件赋值:样本类型,排序要求,数据源筛选。

    使用 HealthKit 的方法进行查询,返回的结果在 result 中,返回的是样本的数组。
    至此, HealthKit 这块的内容都完成了。

    其它 UI

    接下来就是 UI ,和 objective-C 并没有什么太大的区别,稍微值得看的一些地方:

    在实现运动时长设定的时候自定义的一个 UIPickerView 。( HHAddStepsViewController.swift )
    项目中对 NSDate 的处理以及格式化文本。( HHAddStepsViewController.swift )
    tableview 设置自己想贴上 FirstResponderView 。( HHAddStepsViewController.swift )
    加载本地网页和拉取更新服务器上的网页。( HHRootViewController.swift &
    HHAboutViewController.swift )
    拿到数据样本之后在 tableview 中的显示。( HHHistoryViewController.Swift )
    Swift 支持 Objective-C 代码

    项目的最后加上了谷歌分析的代码,首先新建一个头文件命名的时候按照如下格式 ProjectName-Bridging-Header.h ,在头文件中 #import 所以你需要的 Objective-C 头文件。然后选中 Target 选择 build settings ,搜索 Swift 找到 objective -c bridging-header 然后填上你写的头文件的路径。最后你就可以用 Swift 文件中调用 Objective-C 的类了。

    以上希望能帮助一下大家成功开发出自己的计步神器。

    关于好连团队

    专注于连通人、电视大屏及移动互联网的大屏智能化基础设施开发,产品是“好连遥控” APP 以及面向开发者的好连 SDK 。通过好连遥控不仅可以把触摸的体验搬上电视,还能将移动互联网完善的生态,如支付、社交分享等引入电视。让电视用户获得更好的体验的同时,也能帮助开发者更好地在电视上开发、移植和发布应用。

    了解更多关于好连遥控 , www.hihex.com/download/
    加入好连或成为好连开发者 [email protected]

    16 条回复    2015-08-25 22:23:46 +08:00
    liuli12
        1
    liuli12  
    OP
       2015-08-20 15:34:26 +08:00
    我太蠢了。。。等我学会用 markdown 插入图片的时候已经没有编辑权限了_(:з」∠)_
    liuli12
        2
    liuli12  
    OP
       2015-08-20 15:34:55 +08:00
    计步神器做出来后页面是这样的

    liuli12
        3
    liuli12  
    OP
       2015-08-20 15:47:51 +08:00
    大家刷榜是这样的↓

    dorentus
        4
    dorentus  
       2015-08-20 16:29:09 +08:00
    想刷榜的话,不是直接在苹果的 Health.app 里面点开步数,然后添加数据点就可以了么……
    liuli12
        5
    liuli12  
    OP
       2015-08-20 16:38:36 +08:00
    @dorentus

    首先,做这个应用的初衷,

    很多像我们父母一样的中老年人使用着旧款(不带有运动追踪协处理器的)苹果设备,还在用着传统的机械计步器,但他们也是希望能轻松记录健康和锻炼情况的。于是我们开发了这个公益应用,让他们自己或者在帮助下也能记录锻炼情况。

    不是为了刷榜用 der ╮(╯▽╰)╭
    imn1
        6
    imn1  
       2015-08-20 16:39:16 +08:00
    参考最近的一则新闻,先说说能不能识别人腿和狗腿?
    liuli12
        7
    liuli12  
    OP
       2015-08-20 16:44:01 +08:00
    @imn1 这不是像乐动力或咕咚那样的应用。

    用着传统计步器↓
    http://image.big5.made-in-china.com/2f0j01mvFELNABQrkW/%E8%AE%A1%E6%AD%A5%E5%99%A8.jpg

    或是其他不能直接连接微信运动的手环的使用者
    把计步器上的步数手动输入到计步神器里后,微信运动里就会有数据了~~

    是这样的。。
    Jat001
        8
    Jat001  
       2015-08-21 13:45:12 +08:00
    这圈子好小,看头像有点眼熟,看了 ID 才想起来……
    liuli12
        9
    liuli12  
    OP
       2015-08-21 16:12:39 +08:00
    @Jat001 咦?你认识我吗
    Jat001
        10
    Jat001  
       2015-08-21 16:37:33 +08:00
    @liuli12 桃源村看房子的时候
    Heracles
        11
    Heracles  
       2015-08-21 17:02:20 +08:00
    @Jat001 我就不说租房的时候我们、房东、前房客齐聚一堂的时候发现大家都是 IT 从业者了。
    liuli12
        12
    liuli12  
    OP
       2015-08-25 11:50:32 +08:00
    @Jat001 啊是你! 你还记得我啊
    liuli12
        13
    liuli12  
    OP
       2015-08-25 11:52:27 +08:00
    @Heracles 好羡慕, IT 从业者,听起来好高大上的样子
    Heracles
        14
    Heracles  
       2015-08-25 13:07:32 +08:00
    @liuli12 那你说个接地气的说法
    liuli12
        15
    liuli12  
    OP
       2015-08-25 15:43:35 +08:00
    @Heracles 我~ 唔~知啊~ ~~ ~~~
    sobigfish
        16
    sobigfish  
       2015-08-25 22:23:46 +08:00
    @dorentus 手动添加的数据有特定的标记的 虽然没去看 API 但应该能区分出来
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   967 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 20ms · UTC 22:30 · PVG 06:30 · LAX 14:30 · JFK 17:30
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.