in Health Kit Swift ~ read.

Health Kit教程(二)

引言

继续Health Kit的教程,上篇文章Health Kit教程(一)中介绍了关于Health Kit的基础用法。而这篇文章的基础就是建立在上篇文章的基础上,如果对于Health Kit的基础还不是很熟悉的童鞋可以阅读上篇文章来学一些基础的Health Kit的基础用法,然后再来看这篇文章。这篇文章主要是针对在一次运动中的一系列数据进行处理的方法。我们都知道,在一次运动中不可能只是一个数据的变化,有可能有多个数据的变化。就用跑步来说,跑步过程中除了心率变化外,还有一些列的其他数据变化如距离、卡路里消耗等等。所以对于一次运动过程中则需要对于多个数据进行处理。

本片文章是在Xcode 7.1 / Swift 2.0的基础上进行开发的。

处理运动

保存体能训练

在一次运动中,我们需要对多种数据进行处理,而如果为每个数据都单独进行处理的话,没办法看出各个数据之间的关系。而Health Kit针对这点则提出了一个概念为Workout(体能训练),即可以将多种数据的变化添加到一个Workout进行处理。就好像是一个购物清单一样,里面包含着各种数据指标的变化。同理,一个体能训练可以管理多种数据。 这里我们就举一个最简单的运动类型----跑步,这篇文章就针对跑步进行讲解。假设在跑步过程中我们只考虑一下几个指标:距离、消耗时间以及消耗的卡路里。 那么开始上代码吧,先再工具类中添加一个方法用于保存体能训练的数据:

    class func saveRunWorkout(startDate:NSDate , endDate:NSDate , distance:Double, distanceUnit:HKUnit , kiloCalories:Double,
        completion: ( (Bool, NSError!) -> Void)!) {

            // 1. 为距离和
            let distanceQuantity = HKQuantity(unit: distanceUnit, doubleValue: distance)
            let caloriesQuantity = HKQuantity(unit: HKUnit.kilocalorieUnit(), doubleValue: kiloCalories)

            // 2. 保存一个跑步记录
            let workout = HKWorkout(activityType: HKWorkoutActivityType.Running, startDate: startDate, endDate: endDate, duration: abs(endDate.timeIntervalSinceDate(startDate)), totalEnergyBurned: caloriesQuantity, totalDistance: distanceQuantity, metadata: nil)
            store.saveObject(workout, withCompletion: { (success, error) -> Void in
                if( error != nil  ) {
                    // 保存错误的时候将错误传递到调用的闭包
                    completion(success,error)
                } else {
                    // 保存成功
                    completion(success,nil)
                }
            })
    }

然后再写一个界面进行添加,主要是针对几个数值进行添加:

  • 开始时间
  • 持续时间
  • 距离
  • 卡路里消耗

对于建立一个体能训练(Workout类型)的数据主要针对的就是这四个数值进行建立,可以除了上述代码中的方法还可以通过其他方法来进行创建Workout类型的保存点。通过上述方法即可在Health Kit中的健身数据-体能训练中保存一个数据点。大家可以通过保存好一个数据后进行查看是否保存成功。

保存与之相关的数据点

在保存体能训练的过程中,从界面上我们好像是看到了卡路里以及距离的填写,可是到Health Kit中会发现找不到卡路里以及距离的数据点。保存体能训练只是会保存一个体能训练,需要对自己想要保存的相关联的数据点进行再一次保存才可以。感觉这里Healthk Kit应该添加一个bool类型的变量,如果需要保存数据点的话,应该自己动去保存。要不然开发者需要针对这个部分再进行保存一次。 那么接下来再上述方法上在进行改进一下吧:

    class func saveRunWorkout(startDate:NSDate , endDate:NSDate , distance:Double, distanceUnit:HKUnit , kiloCalories:Double,
        completion: ( (Bool, NSError!) -> Void)!) {

            // 1. 为距离和
            let distanceQuantity = HKQuantity(unit: distanceUnit, doubleValue: distance)
            let caloriesQuantity = HKQuantity(unit: HKUnit.kilocalorieUnit(), doubleValue: kiloCalories)

            // 2. 保存一个跑步记录
            let workout = HKWorkout(activityType: HKWorkoutActivityType.Running, startDate: startDate, endDate: endDate, duration: abs(endDate.timeIntervalSinceDate(startDate)), totalEnergyBurned: caloriesQuantity, totalDistance: distanceQuantity, metadata: nil)
            store.saveObject(workout, withCompletion: { (success, error) -> Void in
                if( error != nil  ) {
                    // 保存错误的时候将错误传递到调用的闭包
                    completion(success,error)
                } else {
                /// --------------------------修改部分----------------------
                    // 如果保存成功的话,将建立新的相关数据到Health Kit,即存储距离和卡路里消耗的点数到Health Kit
                    let distanceSample = HKQuantitySample(type: HKQuantityType.quantityTypeForIdentifier(HKQuantityTypeIdentifierDistanceWalkingRunning)!, quantity: distanceQuantity, startDate: startDate, endDate: endDate)
                    let caloriesSample = HKQuantitySample(type: HKQuantityType.quantityTypeForIdentifier(HKQuantityTypeIdentifierActiveEnergyBurned)!, quantity: caloriesQuantity, startDate: startDate, endDate: endDate)

                    // 保存卡路里和距离,并且与之前的Workout相关联
                    store.addSamples([distanceSample,caloriesSample], toWorkout: workout, completion: { (success, error ) -> Void in
                        // 保存成功
                        completion(success,nil)
                    })
                }
            })
    }

可以看到上述代码中的修改部分,可以看得出只需在保存Workout类型的数据点成功后,在添加对应的卡路里以及距离的数据点,保存的时候与Workout进行连接即可。这样单进入Health Kit后就会发现新保存的体能训练所带的卡路里消耗以及距离的数据点也保存下来了。且数据点是可以点击的,可以查看到与之相关联的内容。

获得运动数据

既然保运动数据,那么有的时候我们需要对这些运动数据进行获取。那么该如何获取呢?其实也是非常简单的,跟读取普通的数据点也是差不多的,只需添加以下的方法:

    class func readRunningWorkOuts(completion: (([AnyObject]!, NSError!) -> Void)!) {

        // 1. 设置读取类型
        let predicate =  HKQuery.predicateForWorkoutsWithWorkoutActivityType(HKWorkoutActivityType.Running)
        // 2. 设置排序字段
        let sortDescriptor = NSSortDescriptor(key:HKSampleSortIdentifierStartDate, ascending: false)
        // 3. 创建一个查询的Query
        let sampleQuery = HKSampleQuery(sampleType: HKWorkoutType.workoutType(), predicate: predicate, limit: 0, sortDescriptors: [sortDescriptor])
            { (sampleQuery, results, error ) -> Void in

                if let queryError = error {
                    print( "读取跑步数据的时候发生错误, Error: \(queryError.localizedDescription)")
                }
                completion(results,error)
        }
        // 4. 执行查询的Query
        store.executeQuery(sampleQuery)

    }

需要注意的是,这里获得的是体能训练的数据。也就是说即使不保存对应相关联的数据点也能从体能训练中获得对应的卡路里消耗以及距离等数据的信息,因为可以从保存体能训练中看的出,体能训练创建的时候也是保存了这些数据信息的。所以对于那些偷懒的小伙伴们,可以直接从体能训练中获得卡路里消耗以及距离的信息。最后添加一个对应的界面来查询即可。

总结

从这两篇文章可以看出,其实Health Kit的简单数据保存和读取其实还是非常简单的。Health Kit更像是一个数据库,我们与Health Kit的交互就如是于数据库进行交互,读取和保存。而对于普通的App来说,以上说的内容也大体能用了,只需稍加进行变动和修改即可。如果小伙伴在使用的过程中还有遇到什么其他的问题,可以联系我的微博叫什么都不如叫Pluto-Y来联系我,或者去我的Github上下载代码来研究。好吧最后来看看运行的效果吧。

运行效果

comments powered by Disqus