>心率测试可以算是apple watch的一个很大的特性,很多健康或者运动类app都会用到心率相关功能,这篇文章我们就来讲讲在watch OS2中心率开发的一些知识点,全文将使用swift进行描述。 ### 导入头文件、声明变量 - 我们要做的第一步当然是导入头文件: ``` import HealthKit ``` 我们接下来要用到的所有api都在这个头文件里。 - 声明一个workOut变量 ``` self.workoutSession = HKWorkoutSession(activityType: HKWorkoutActivityType.CrossTraining, locationType: HKWorkoutSessionLocationType.Indoor)         self.workoutSession?.delegate = self ``` 这个变量中有两个参数 ``` /*!      @method        initWithActivityType:locationType:           @param         activityType    The activity type of the workout session.      @param         locationType    The type of location where the workout will be performed.      */     public init(activityType: HKWorkoutActivityType, locationType: HKWorkoutSessionLocationType) ``` 第一个参数选择活动的类型、第二个参数选择活动的地点。 (其实我并不清楚选择不同的参数对我们的结果有什么影响,也许是苹果在不同的参数下选择了不同的算法) HKWorkoutSessionDelegate中有两个方法需要我们来实现,第一个是活动启动失败的回调,第二个就是活动状态发生变化。 ```  func workoutSession(workoutSession: HKWorkoutSession, didChangeToState toState: HKWorkoutSessionState, fromState: HKWorkoutSessionState, date: NSDate){              switch toState {         case .Running:             workoutDidStart()             break         case .Ended: break //            workoutDidEnd(date)         default:             print("Unexpected state \(toState)")         }     }     func workoutSession(workoutSession: HKWorkoutSession, didFailWithError error: NSError){         print(error)         print("workout fail")     } ``` 我们在活动启动成功以后开始查询心率。 (启动成功以后我们的手表表低将发出蓝光,使用光电进行心率测试) - 使用HKHealthStore启动活动 ```     let healthStore = HKHealthStore()     let quantityType = HKQuantityType.quantityTypeForIdentifier(HKQuantityTypeIdentifierHeartRate)//指定活动类型  let dataTypes = Set(arrayLiteral: self.quantityType!)         self.healthStore.requestAuthorizationToShareTypes(nil, readTypes: dataTypes) { (success, error) in                      }    healthStore.startWorkoutSession(self.workoutSession!) ``` 在这里我们使用quantityType来指定我们的活动类型。 我们已经成功的启动了我们的活动,如果启动成功或者失败,将在workoutSession的回掉中反馈给你。 - 活动启动成功,查询心率 当我们的活动启动成功以后,手表将读取到的心率保存到手机端的“健康”当中,我们需要对健康中的数据进行查询; ```  let predicate = HKQuery.predicateForSamplesWithStartDate(NSDate(), endDate: nil, options: .None)     let anchor = HKQueryAnchor(fromValue: Int(HKAnchoredObjectQueryNoAnchor)) func workoutDidStart(){                  let heartRateQuery = HKAnchoredObjectQuery(type: quantityType!, predicate: predicate, anchor: anchor, limit: HKObjectQueryNoLimit) { (query, Sample, deletedObjects, newAnchor, error) in             print(error)             if Sample != nil{                 print("start:"+(Sample?.description)!)             }         }         heartRateQuery.updateHandler = {(AnchoredObjectQuery:HKAnchoredObjectQuery, Sample:[HKSample]?, DeletedObject:[HKDeletedObject]?, Anchor:HKQueryAnchor?, error:NSError?) -> Void in             print("update:"+(Sample?.description)!)         }         healthStore.executeQuery(heartRateQuery)              } ``` 这段代码非常好理解,我们声明了一些查询的变量,然后使用 healthStore对心率进行了查询,巴拉巴拉~~~ ### 授权 我们信心慢慢的启动了应用,掷地有声的表明代码绝对没有问题,然后还是出现了问题,XCode抛出了一个错误: ``` Error occurred = Error Domain=com.apple.healthkit Code=4 "Missing com.apple.developer.healthkit entitlement." UserInfo=0x7fa748534b00 {NSLocalizedDescription=Missing com.apple.developer.healthkit entitlement.} ``` 我们要知道苹果对隐私是十分关注的,而健康数据则是重中之重,所以苹果对这方面的权限十分关注,以上这个报错是因为我们缺少了开启心率记录的权限,解决方法如下图: ![Paste_Image.png](/static/images/essay/4.png) 我们将healthKit的开关打开,这样我们就有调用healthKit相关api的能力了。 我们满心以为现在代码没有问题了,再次启动应用,然而却还是报错了: ![Paste_Image.png](/static/images/essay/5.png) 这个报错是因为我们想要查询健康中的数据,却没有进行授权,所以我们需要在iPhone端进行授权: 我们在iPhone的delegate中加入以下代码: ``` func applicationShouldRequestHealthAuthorization(application: UIApplication) {         let healthStore = HKHealthStore()         self.healthStore.handleAuthorizationForExtensionWithCompletion { success, error in                      }     } ``` 这段代码将对健康数据读取进行授权,启动应用,将提示我们在iPhone端进行授权,来带iPhone端则是会打开健康授权界面,这时候我们允许读取心率即可。 现在再启动应用,我们终于读取到了心率数据,数据将在 heartRateQuery的回调中返回,回掉中有一个参数是[HKSample]?在这个参数中我们可以读取到我们的心率数值,像这样 ```     let heartRateUnit = HKUnit(fromString: "count/min") guard let sample = heartRateSamples.first else{return}     let value = sample.quantity.doubleValueForUnit(self.heartRateUnit) ``` ### 停止心率测试 停止心率测试和进行心率查询基本类似,还是同样的变量,这里不再重复声明: ```             healthStore.stopQuery(p.p1 {heartRateQuery) ``` ---------------- 以上则是进行心率测试的基本内容。 ### 欢迎加入iOS交流群537774852