计步器对于 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
}
}
}
}
复制代码