使用CMPedometer的iWatch准确计算步数

Apple Watch Series 3具有大量传感器,处理速度显着提高,这使其成为功能强大的机器,可以比以前的Watch版本更好地跟踪和评估您的健身数据。

我最近正在研究计步器类型应用程序的实现,在该应用程序中,我必须准确确定iWatch用户采取的步骤。 对于此用例,我决定使用Core Motion框架的CMPedometer。

CMPedometer基本上让您跟踪:

  • 步数
  • 行驶距离
  • 根据爬了多少楼梯的楼层数
  • 你走多快或多慢

iWatch跟踪此信息的方式是通过消耗iPhone中集成的加速度计,陀螺仪,磁力计和指南针生成的数据。

CMPedometer是Core Motion框架的一部分,该框架使您可以访问iPhone 5S及更高版本上的内置运动处理器。 它可以处理从集成的加速度计,陀螺仪,磁力计和气压计生成数据(尽管iPhone 6提供了气压计)。 iWatch处理器始终跟踪此数据并临时存储以供使用。 请务必注意,Core Motion只能在任何时间存储当前的7天时间段。

开发健身应用程序的任何人都可以使用Core Motion来同时使用iPhone和iWatch测量运动类型。 除了跑步,散步和骑自行车等常见活动外,iWatch还可以帮助跟踪众多其他户外运动。

CMP计

为了获取步数和有关行进距离的其他详细信息,我使用了计步器对象。 可以使用计步器对象查询历史数据的缓存信息。 除此之外,同一个对象使我们能够在处理数据时获取实时信息。

您可以使用计步器实例来调用以下类型的方法。

  1. 使用queryPedometerData(from:to:withHandler:)获取历史数据
  2. 使用startUpdates(from:withHandler:)放置观察者实时更新

让我们开始一个演示计算步骤,距离和楼层数(爬楼梯)的演示。 但是,让我们先谈谈隐私!

CMPedometer更具体地使用了Apple认为私有数据的几种动作 。 在计步器上,您还将使用位置数据,因此隐私是一个更大的问题。 开发人员需要在info.plist中添加密钥NSMotionUsageDescription来征求用户的许可。 您可以在plist中添加密钥,如下所示:

步骤1:导入Core Motion

您需要先导入核心运动才能使用CMPedometer。

  //导入CoreMotion 
 导入CoreMotion 

步骤#2:创建CMPedometer的实例

让我们创建CMPedometer实例并需要变量

  // MARK:-变量 
  fileprivate let计步器= CMPedometer() 
  fileprivate var startDate:日期?  =无 
  fileprivate var timeElapsed:TimeInterval = 1.0 
  fileprivate var numberOfSteps:Int!  = 0 
  fileprivate var distance:Double!  = 0.0 
  fileprivate var步伐:翻倍!  = 0.0 
  fileprivate var averagePace:Double!  = 0.0 
  Fileprivate var FloorsAscended:整数!  = 0 
  Fileprivate var FloorsDscended:Int!  = 0 
  fileprivate var cadence:Double!  = 0 

步骤#3:检查数据是否可用

在使用计步器数据之前,我们需要检查该数据是否在当前设备中可用?

  ///检查步骤计数在设备中是否可用 
  var isStepCountingAvailable:布尔{ 
 得到{ 
 返回CMPedometer.isStepCountingAvailable() 
  } 
  } 
  ///检查设备中的步速是否可用 
  var isPaceAvailable:布尔{ 
 得到{ 
 返回CMPedometer.isPaceAvailable() 
  } 
  } 
  ///检查距离是否在设备中可用 
  var isDistanceAvailable:布尔{ 
 得到{ 
 返回CMPedometer.isDistanceAvailable() 
  } 
  } 
  var isCadenceAvailable:布尔{ 
 得到{ 
 返回CMPedometer.isCadenceAvailable() 
  } 
  } 
  ///检查楼层数是否在设备中可用 
  var isFloorCountingAvailable:布尔{ 
 得到{ 
 返回CMPedometer.isFloorCountingAvailable() 
  } 
  } 

让我们为此演示设置一个基本的UI。 像这样:

步骤#4:连接渠道和行动

并连接上述标签和按钮的插座和操作。

  //标记:-IBOutlets 
  @IBOutlet var lblTime:WKInterfaceLabel! 
  @IBOutlet var lblSteps:WKInterfaceLabel! 
  @IBOutlet var lblCadence:WKInterfaceLabel! 
  @IBOutlet var lblPace:WKInterfaceLabel! 
  @IBOutlet var lblAvgPace:WKInterfaceLabel! 
  @IBOutlet var lblDistance:WKInterfaceLabel! 
  @IBOutlet var lblFloorsUp:WKInterfaceLabel! 
  @IBOutlet var lblFloorsDown:WKInterfaceLabel! 
  @IBOutlet var btnStartUpdating:WKInterfaceButton! 
  var startDate:日期? 
  //标记:-动作方法 
  @IBAction func btnStartClicked(){ 
  } 

步骤5:检查授权状态

现在,让我们开始观察步骤。 因此,在确定计步器的可用性之后,我们需要检查CMPedometer的授权状态。

 私有函数checkAuthorizationStatus()-> Bool { 
  var pedoMeterAuthorized = false 
 开关CMPedometer.authorizationStatus(){ 
 大小写被拒绝: 
  onStop() 
  case .authorized:pedoMeterAuthorized = true 
 默认值:break 
  } 
 返回pedoMeterAuthorized 
  } 

我们差不多完成了,让我们从block开始观察者。

 公共变量stepCountingHandler:((( ? 
 私人功能startTrackingSteps(){ 
  pedometer.startUpdates(from:Date(),withHandler: 
{(pedometerData,error)in
 如果让pedData = pedometerData { 
  self.setPedometerData(pedData:pedData) 
 如果self.stepsCountingHandler!=无 
  { 
  self.stepsCountingHandler?(self.numberOfSteps,self.distance,self.averagePace,self.pace,self.floorsAscended,self.floorsDscended,self.cadence,Date()。secondsInBetweenDate(self.startDate)) 
  } 
  }其他{ 
  self.numberOfSteps =无 
  } 
  }) 
  } 
 私人功能setPedometerData(pedData:CMPedometerData) 
  { 
  self.numberOfSteps = Int(截断:pedData.numberOfSteps) 
 如果让distancee = pedData.distance { 
  self.distance = Double(截断:distancee) 
  } 
 如果让averageActivePace = pedData.averageActivePace { 
  self.averagePace = Double(截断:averageActivePace) 
  } 
 如果让currentPace = pedData.currentPace { 
  self.pace = Double(截断:currentPace) 
  } 
 如果让floor = pedData.floorsAscended { 
  self.floorsAscended = Int(截断:floor) 
  } 
 如果让floor = pedData.floorsDescended { 
  self.floorsDscended = Int(截断:floor) 
  } 
 如果让cadence = pedData.currentCadence { 
  self.cadence = Double(截断:节奏) 
  } 
  } 

在接口控制器上添加处理程序,以便我们可以在那里绑定数据。

  activityHelper.stepsCountingHandler = {步距,距离, 
平均步伐,步伐,楼层升序,楼层Dscended,节奏,
时间在
  self.lblSteps.setText(“ Steps:\(steps”“) 
  self.lblDistance.setText(“ Distance:\(distance)”) 
  self.lblAvgPace.setText(“ Avg Pace:\(averagePace)”) 
  self.lblPace.setText(“ Pace:\(pace)”) 
  self.lblCadence.setText(“ Cadence:\(cadence)”) 
  self.lblFloorsUp.setText(“节奏:\(floorsAscended)”) 
  self.lblFloorsDown.setText(“节奏:\(floorsDscended)”) 
  self.lblTime.setText(“时间:\(timeElapsed)秒”) 
  } 

步骤6:获取历史计步器数据

  activityHelper.getStepsDataFor(startDate:startDate, 
  endDate:endDate, 
  successBlock:{ 
  (步数,距离,平均步速,步速,地板升序,地板Dscended,节奏,经过的时间) 
  self.lblSteps.setText(“ Steps:\(steps”“) 
  self.lblDistance.setText(“ Distance:\(distance)”) 
  self.lblAvgPace.setText(“ Avg Pace:\(averagePace)”) 
  self.lblPace.setText(“ Pace:\(pace)”) 
  self.lblCadence.setText(“ Cadence:\(cadence)”) 
  self.lblFloorsUp.setText(“节奏:\(floorsAscended)”) 
  self.lblFloorsDown.setText(“节奏:\(floorsDscended)”) 
  self.lblTime.setText(“时间:\(timeElapsed)秒”) 
  },errorBlock:{(错误)在 
  }) 

这就是最终结果的样子。 😎

计步器是“核心运动”的高级对象。 它设置自己的刷新率,我们可以通过闭包获取更新,因此它是按自己的时间表进行的,而不是我们可以控制的。 您可以从此处下载完整代码。

Interesting Posts