当前位置: 首页 > 工具软件 > Pedometer > 使用案例 >

CMPedometer 计步器的使用—— 基于API分析

桓嘉谊
2023-12-01

计步器对于 iOS 开发来说应该门槛很低,苹果爸爸给做的很清楚明了了,调用 API 就可以了。 使用计步器可以做哪些事情呢?具体如下: 1.查询历史步数记录,最多七天的 2.实时更新当天的数据 3.查询行走的步数、距离、上下的楼层、实时监测你的速度

##查询计步器数据的两个方法: 1.查询计步器在指定时间范围内的数据。

func queryPedometerData(from start: Date, to end: Date, 
            withHandler handler: @escaping CMPedometerHandler)
复制代码

2.指定一个起始时间,更新截止到现在的数据。

func startUpdates(from start: Date, withHandler handler: @escaping CMPedometerHandler)
复制代码

计步器可以通过调用stopPedometerUpdates来停止更新。

##源码分析 ###CMPedometer 类

@available(iOS 8.0, *)
open class CMPedometer : NSObject {

// 返回一个布尔值,指示当前设备上是否有步数计数。
    open class func isStepCountingAvailable() -> Bool

// 返回一个布尔值,指示距离估计是否在当前设备上可用。
    open class func isDistanceAvailable() -> Bool

// 返回一个布尔值,指示当前设备是否可以使用楼层计数。
    open class func isFloorCountingAvailable() -> Bool

// 返回一个布尔值,指示当前设备上是否有速度信息可用。
    @available(iOS 9.0, *)
    open class func isPaceAvailable() -> Bool

// 返回一个布尔值,指示节奏信息是否在当前设备上可用。
    @available(iOS 9.0, *)
    open class func isCadenceAvailable() -> Bool

// 返回一个布尔值,指示当前设备是否可以使用计步器事件。
    @available(iOS 10.0, *)
    open class func isPedometerEventTrackingAvailable() -> Bool

// 查询指定时间内的计步器的历史记录。 数据最多可以使用7天,距离结束日期最近的7天。 结果返回串行队列。
    open func queryPedometerData(from start: Date, to end: Date, withHandler handler: @escaping CoreMotion.CMPedometerHandler)

    
// 开始一系列持续的计步器更新。 对于每个更新,应用程序自此以后将会收到从指定的开始日期所累积的步数。
    open func startUpdates(from start: Date, withHandler handler: @escaping CoreMotion.CMPedometerHandler)

// 停止更新计步器
    open func stopUpdates()

// 在串行队列上启动计步器事件更新。事件仅在应用程序在前台/后台运行时可用。
    @available(iOS 10.0, *)
    open func startEventUpdates(handler: @escaping CoreMotion.CMPedometerEventHandler)

// 停止启动计步器事件更新。
    @available(iOS 10.0, *)
    open func stopEventUpdates()
}

复制代码

###CMPedometerData 类

 // 这是 CMPedometerData 类,就是为我们访问到的硬件设备所记录的数据。类中包括的属性有步数、速度、楼层等信息
@available(iOS 8.0, *)
open class CMPedometerData : NSObject, NSSecureCoding, NSCopying {

    
// 开始日期:计步器数据有效期间的开始时间,这是会话或历史查询请求的开始时间。
    open var startDate: Date { get }

// 结束日期:计步器数据有效期的结束时间。对于更新而言,这是最新更新的截止时间时间。 对于历史查询这是所请求的结束时间。
    open var endDate: Date { get }

// 用户的步数
    open var numberOfSteps: NSNumber { get }
  
// 距离: 行走时用户行驶的预计距离(米)
    open var distance: NSNumber? { get }

// 上的楼梯数: 上的楼梯大致数量
    open var floorsAscended: NSNumber? { get }

// 下的楼梯数: 下的楼梯大致数量
    open var floorsDescended: NSNumber? { get }

/*
     当前速度
     对于更新,将以s / m(每米秒)返回当前速度。
     如果以下任何一项为真,则值为零:
    (1)信息尚未公布;
    (2)历史查询;
    (3)不支持的平台。
 */
    @available(iOS 9.0, *)
    open var currentPace: NSNumber? { get }

// 当前的步速: 步/秒
   @available(iOS 9.0, *)
    open var currentCadence: NSNumber? { get }

// 平均速度
    @available(iOS 10.0, *)
    open var averageActivePace: NSNumber? { get }
}
复制代码
// 计步器运动类型: 是个枚举类型,枚举值为:暂停 和 继续 
@available(iOS 10.0, *)
public enum CMPedometerEventType : Int {

    case pause

    case resume
}

复制代码

###CMPedometerEvent 类

// 标志用户活动变化事件的类

@available(iOS 10.0, *)
open class CMPedometerEvent : NSObject, NSSecureCoding, NSCopying {

//  事件发生的时间。
    open var date: Date { get }

// 描述行人活动过渡的事件类型。上边的枚举
    open var type: CMPedometerEventType { get }
}

// CMPedometerHandler 类型别名,是一个当计步器数据可用时要调用的函数块。参数为CMPedometerData 和 Error, 无返回值 
public typealias CMPedometerHandler = (CMPedometerData?, Error?) -> Swift.Void


@available(iOS 10.0, *)
public typealias CMPedometerEventHandler = (CMPedometerEvent?, Error?) -> Swift.Void

复制代码

到此就看完整个CMPedometer的属性方法了,那么如何使用呢?

##========== 华丽丽分割线,上示例代码 ============

**注意:**支持 iOS10.0 以上设备,并且在我们访问设备数据的时候需要在 info.plist 文件中添加键值:Privacy - Motion Usage Description 如图:

当你运行程序的时候,就会提醒你,和访问相机权限一样。

以下是实现代码:

//  ViewController.swift
//  Pedometer
//  Created by YHY on 2017/3/19.
//  Copyright © 2017年 太阳在线. All rights reserved.

import UIKit
import CoreMotion

class ViewController: UIViewController {

	let pedometer = CMPedometer()
	
	@IBOutlet weak var stepNumber: UITextView!

	@IBOutlet weak var stepNumber1: UITextView!

	override func viewDidLoad() {
		super.viewDidLoad()
		
		// 更新当日的步数
		getPedometerData()
		
      // 获取历史记录步数
		getSometimePedometer()
		
	}
	
	
	func getPedometerData() {

		//判断设备支持情况
		guard CMPedometer.isStepCountingAvailable() else {
			self.navigationItem.title = "当前设备不支持获取步数"
			return
		}
		
		//获取今天凌晨时间
		let calendar = Calendar.current
		print(calendar)
		var components = calendar.dateComponents([.year, .month, .day], from: Date())
		print(components)
		components.hour = 0
		components.minute = 0
		components.second = 0
		let date = calendar.date(from: components)!
		
		
		//初始化并开始实时获取数据
	
		self.pedometer.startUpdates(from: date) { (pedometerData, error) in
			
			//错误处理
			guard error == nil else {
				print(error!)
				return
			}
	
			//获取各个数据
			var stepData = "---今日运动数据---\n"
			if let numberOfSteps = pedometerData?.numberOfSteps {
				stepData += "今日已走\(numberOfSteps)步\n"
				print(stepData)
			}
			if let distance = pedometerData?.distance {
				stepData += "今日已走\(distance)米\n"
				print(stepData)
			}
			if let floorsAscended = pedometerData?.floorsAscended {
				stepData += "今日上楼\(floorsAscended)层\n"
				print(stepData)
			}
			if let floorsDescended = pedometerData?.floorsDescended {
				stepData += "今日下楼\(floorsDescended)层\n"
				print(stepData)
			}
			//print(pedometerData?.currentPace,pedometerData?.currentCadence)
			if let currentPace = pedometerData?.currentPace {
				stepData += "步行速度\(currentPace)m/s\n"
				print(stepData)
			}
			if let currentCadence = pedometerData?.currentCadence {
				stepData += "步速为 \(currentCadence)步/秒"
				print(stepData)
			}
			
			
			//在线程中更新文本框数据
			DispatchQueue.main.async{
				self.stepNumber.text = stepData
			}
		}
	}
	
	func getSometimePedometer() {
		
		let date = Date()
		
		print(date)
		
		//判断设备支持情况
		guard CMPedometer.isStepCountingAvailable() else {
			self.navigationItem.title = "当前设备不支持获取步数"
			return
		}
		
		let dataoformatter = DateFormatter()
		dataoformatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
		
		let string = dataoformatter.string(from: date)
		print(string)
		
		let fromeDate = dataoformatter.date(from: "2017-03-11 00:00:00")
		let toDate = dataoformatter.date(from: string)
		
		var stepData = "---查询历史运动数据---\n"
		
		// 查询从 fromeDate 到 toDate 走的步数
		pedometer.queryPedometerData(from: fromeDate!, to: toDate!) { (pedometerData, error) in
			//获取各个数据
		
			if let numberOfSteps = pedometerData?.numberOfSteps {
				stepData += "已走\(numberOfSteps)步\n"
				print(stepData)
			}
			if let distance = pedometerData?.distance {
				stepData += "已走\(distance)米\n"
				print(stepData)
			}
			if let floorsAscended = pedometerData?.floorsAscended {
				stepData += "上楼\(floorsAscended)层\n"
				print(stepData)
			}
			if let floorsDescended = pedometerData?.floorsDescended {
				stepData += "下楼\(floorsDescended)层\n"
				print(stepData)
			}
	//print(pedometerData?.currentPace,pedometerData?.currentCadence)
			if let currentPace = pedometerData?.currentPace {
				stepData += "步行速度\(currentPace)m/s\n"
				print(stepData)
			}
			if let currentCadence = pedometerData?.currentCadence {
				stepData += "步速为 \(currentCadence)步/秒"
				print(stepData)
			}
			
			DispatchQueue.main.async{
				self.stepNumber1.text = stepData
			}
		}
	}
}

复制代码

Demo 下载

 类似资料: