简介

iOS8以后,CoreMotion框架中为我们提供了一个获取用户活动信息的目标CMPedometer,经过CMPedometer我们能够获取用户的活动信息,如:行走步数,行走的公里数,上下楼层数以及平均速度等。以获取运动步数为例:

iOS中获取运动步数,一般有两种办法:

  • CMPedometer
  • HealthKit框架从手机健康App中获取数据

需求了解HealthKit能够看这个:HealthKit

其实健康App也是经过CMPedometer获取的步数,两者得到步数有一定的差异,一般后者的数据比前者多。

由于CMPedometer获取的是iPhone的步数,假如用户佩戴iWatch的话,在相同或有交叉时刻内,iPhone和iWatch都记录了运动步数,笔者猜想健康App进行了一些校准和优化算法,比方存在iWatch数据,假如同一时刻段iPhone与iWatch都运动的话,猜想取的是数值较高的那一组设备数据。

两种办法都需求用户授权,一般我们需求获取用户运动步数的时候,优先运用第二种,从健康App中获取数据。假如用户不授权,则再经过CMPedometer获取步数。

留意

需求留意的是,健康App中的步数值,用户是能够手动修改添加的,所以我们在获取的时候,一定要过滤人为手动修改的值。

CMPedometer

基础类

  • CMPedometer:计步器类
  • CMPedometerEvent:计步器事情类
  • CMPedometerData:计步器数据类,步数,间隔,楼层等信息经过此类获取

相关功用判别:

  • isStepCountingAvailable:是否支撑步数计数功用
  • isDistanceAvailable:是否支撑间隔估量
  • isFloorCountingAvailable:是否支撑核算楼梯段数
  • isPaceAvailable:是否支撑速度估量
  • isCadenceAvailable:是否支撑频率预算
  • isPedometerEventTrackingAvailable:是否支撑计步器事情

留意事项:

  • 需导入<CoreMotion/CoreMotion.h>
  • 此类在iOS8之后才可用,在iOS8之前,运用CMStepCounter类来获取步数(iPhone 5S及以上机型)
  • 运用CMPedometer目标,需求设计成全局特点,强引证,避免提早释放
  • 在info.plist文件中增加NSMotionUsageDescription键,简略描述下

主要办法:

1、

- (void)queryPedometerDataFromDate:(NSDate *)
                       starttoDate:(NSDate *)end 
                       withHandler:(CMPedometerHandler)handler;

在给定时刻范围内查询用户的行走活动,数据最多能够运用7天内有效,回来的数据是从系统范围的历史记录中核算出来的,该历史记录是在后台接连收集的。结果回来在串行队列中。

2、

- (void)startPedometerUpdatesFromDate:(NSDate *)start
                          withHandler:(CMPedometerHandler)handler;

在串行队列上发动一系列接连计步器更新到处理程序。对于每次更新,应用程序将从指定的开端日期和与最新确定相关联的时刻戳开端收到累积的行人活动。假如应用程序在后台进行布景调整,则应用程序将在下次更新中收到在后台期间累积的所有行人活动。

说人话就是从某一时刻段开端,接连的收集步数,间隔,楼层等信息,当设备中的活动数据产生改变就会回调此办法。

对应stopPedometerUpdates办法,中止计步器更新运动数据

3、

- (void)startPedometerEventUpdatesWithHandler:(CMPedometerEventHandler)handler

在串行队列上发动计步器事情更新(事情时刻、暂停、重新开端等、)。事情仅在应用程序在前台/后台运行时可用。

对应stopPedometerEventUpdates办法,中止计步器事情更新

完好代码

#import "ViewController.h"
#import <CoreMotion/CoreMotion.h>
@interface ViewController ()
// 界说为特点,否则或许无法正常获取运动信息
// 若过错Error Domain=CMErrorDomain Code=104(或者103?),则pedometer没有设置为property特点
@property (nonatomic,strong) CMPedometer *pedometer;
@end
@implementation ViewController
- (CMPedometer *)pedometer{
  if(_pedometer == nil){
    _pedometer = [[CMPedometer alloc]init];
  }
  return _pedometer;
}
- (void)viewDidLoad {
  [super viewDidLoad];
    // 经过计步器获取运动信息
    [self usePedometer];
}
- (void)usePedometer{
  if ([CMPedometer isStepCountingAvailable] && 
        [CMPedometer isDistanceAvailable] && 
    [CMPedometer isFloorCountingAvailable] && 
    [CMPedometer isPaceAvailable] && 
    [CMPedometer isCadenceAvailable] && 
    [CMPedometer isPedometerEventTrackingAvailable]){ 
    NSCalendar *calendar = [NSCalendar currentCalendar];
    NSDate *now = [NSDate date];
    // 开端时刻
    NSDate *startDate = [calendar startOfDayForDate:now];
    // 结束时刻
    NSDate *endDate = [calendar dateByAddingUnit:NSCalendarUnitDay value:1 toDate:startDate options:0];
    // 查询当天数据
    [self.pedometer queryPedometerDataFromDate:startDate toDate:endDate withHandler:^(CMPedometerData * _Nullable pedometerData, NSError * _Nullable error) {
      if (error) {
        NSLog(@"获取失败");
      } else {
        // 步数
        double stepCount = [pedometerData.numberOfSteps doubleValue];
        NSLog(@" 经过计步器获取步数: %ld",(long)stepCount);
        // 间隔,若值为nil,不支撑渠道(下同)
        double distance = [pedometerData.distance doubleValue];
        NSLog(@" 经过计步器获取估量间隔(米): %ld",(long)distance);
       
        // 上楼
        NSInteger floorsAscended = [pedometerData.floorsAscended integerValue];
        NSLog(@" 经过计步器获取上楼: %ld",(long)floorsAscended);
       
        // 下楼
        NSInteger floorsDescended = [pedometerData.floorsDescended integerValue];
        NSLog(@" 经过计步器获取下楼: %ld",(long)floorsDescended);
       
        // 速度 s/m
        double currentPace = [pedometerData.currentPace doubleValue];
        NSLog(@" 经过计步器获取速度(秒/米): %ld",(long)currentPace);
       
        // 频率(step/s)
        double currentCadence = [pedometerData.currentCadence doubleValue];
        NSLog(@" 经过计步器获取频率(步/秒): %ld",(long)currentCadence);
       
        // 记得去主线程更新UI
        dispatch_async(dispatch_get_main_queue(), ^{
       
        });      
      }
    }];
   // 获取更新数据
    [self.pedometer startPedometerUpdatesFromDate:[NSDate date] withHandler:^(CMPedometerData * _Nullable pedometerData, NSError * _Nullable error) {
           // 处理同上
     // 中止更新运动数据
     // [self.pedometer stopPedometerUpdates];
    }];
    // 计步器事情
    [self.pedometer startPedometerEventUpdatesWithHandler:^(CMPedometerEvent * _Nullable pedometerEvent, NSError * _Nullable error) {
      // 中止计步器事情更新
      //[self.pedometer stopPedometerEventUpdates];
    }];
  }
}
@end