zoukankan      html  css  js  c++  java
  • iOS加速计和陀螺仪

    https://blog.csdn.net/maiwc/article/details/78644220

    iOS系统提供了加速计和陀螺仪支持,如果iOS设备提供了这些硬件支持,iOS即可通过CoreMotion框架提供的加速计来获取设备当前的加速度数据、陀螺仪数据、所处的磁场以及设备的方位等信息;

    对于iOS应用开发者来说,开发传感器应用十分简单,CoreMotion框架的核心API是CMMotionManager,开发者只要创建一个CMMotionManager对象,接下来即可采用定时器周期性地从CMMotionManager对象获取加速度数据、陀螺仪数据等,也可采用基于代码块的方式来获取这些数据。

    一、iOS支持的加速计和陀螺仪

    加速计可以测出设备的加速度和重力,内置的陀螺仪还可以获取设备的转动,这些数据都通过CMMotionManager对象来获取。而且采用完全类似的方式来获取设备的加速度数据、陀螺仪数据、磁场数据等。

    1、iOS加速计和陀螺仪的理论基础

    iOS加速计是一个三轴加速计,这意味着它可以检测三维空间中的运动和重力,因此加速计不仅可以获取用户握持手机的方向(向上还是向下),而且可以感知手机正面向下还是向上。

    加速计可以测量设备在特定方向的加速度(使用重力g作为单位),当加速度返回值为1.0时,表明设备在特定方向上感知到1g。

    iOS设备的加速计所使用的三轴坐标系统如下: 
    这里写图片描述

    从上图上可以看出:iOS设备的加速计的三轴坐标系统的X、Y、Z轴定义如下:

    • 沿着手机屏幕顶部向上是Y轴正方向,向下是Y轴负方向;

    • 当手机顶部朝上时,沿着手机屏幕向右是X轴正方向,向左是X轴负方向;

    • 正对手机时,垂直屏幕向外是Z轴正方向,垂直屏幕向里是Z轴负方向;

    当手机静止不动时,地球引力将会给予手机1g的加速度。典型的,当用户垂直握持手机切顶部向上时,手机即可检测到大约-1g的加速度:如果用户以45度角握持手机,则1g的加速度将会平均分配到X、Y两个轴上。如果检测到加速度的值远大于1g,即可判断该设备突然发成了运动,比如设备被摇动、坠落等,此时加速度即可在一个或多个轴上检测到较大值。

    除了加速度数据之外,iOS还可以获取陀螺仪数据,陀螺仪数据则可表示设备围绕各坐标轴的转动。例如,把手机平放在桌面上,手机在各方向的加速度基本不会改变,此时手机将会检测到Z轴方向有大约-1g的加速度。如果此时对手机进行旋转,手机的加速度依然不会有明显的改变,但手机陀螺仪将会返回绕Z轴发生转动。如果用户垂直握持手机,并绕垂直轴转动,此时手机检测到的加速度值依然不会发生改变,但手机陀螺仪将会检测到绕Y轴发生的转动。

    简单来说,陀螺仪数据用于检测设备绕X、Y、Z轴转动时的速度,转动越快,陀螺仪返回的数据越大。iOS还可以获取周围磁场在X、Y、Z轴的强度,磁场强度一微特斯拉为单位。

    总结出来,iOS的CMMotionManager大致可获取3种数据:

    • 加速度数据:该数据通过CMAccelerometerData对象来表示。该对象只有一个CMAcceleration结构体类型的acceleration属性,该结构体属性值包含x、y、z三个字段,分别代表设备在X、Y、Z轴方向检测到的加速度值;

    • 陀螺仪数据:该数据通过CMGyroData对象来表示。该对象只有一个CMRotationRate结构体类型的rotationRate属性,该结构体属性值包含x、y、z三个字段,分别代表设备围绕X、Y、Z轴转动的速度;

    • 磁场数据:该数据通过CMMagnetometerData对象来表示。该对象只有一个CMMagneticField结构体类型的magneticField属性,该结构体属性值包含x、y、z三个字段,分别代表设备在X、Y、Z轴方向检测到的磁场强度,以微特斯拉为单位。

    除此之外,CMAccelerometerData、CMGyroData、CMMagnetometerData有一个公共的弗雷:CMLogItem,该弗雷定义了timestamp属性,这意味着不管是加速度数据、陀螺仪数据、磁场数据,都可通过timestamp属性来访问程序得到的该数据的时间。

    iOS应用程序获取加速度数据、陀螺仪数据、磁场数据有如下两种方式:

    • 以基于代码块的方式获取加速度数据、陀螺仪数据、磁场数据,这种方式适用于普通的、实时性要求较低的应用。

    • 以周期性主动请求的方式获取加速度数据、陀螺仪数据、磁场数据,这种方式适用于实时性要求较高,或者程序要随时获取这些数据的应用,比如哟啊感知加速度数据、陀螺仪数据的游戏等。

    2、基于代码块方式获取加速度数据、陀螺仪数据、磁场数据

    如果使用基于代码块的方式来获取加速计数据,请按如下步骤进行:

    • ①、创建CMMotionManager对象;
    • ②、为CMMotionManager设置获取加速度数据。陀螺仪数据、磁场数据的频率,通常就是设置xxxUpdateInterval属性,该属性值的单位是秒。其中xxx代表accelerometer(加速度)、gyro(陀螺仪)和magnetometer(磁场)中任意一个。
    • ③、调用CMMotionManager对象的startXxxUpdatesToQueue:queue withHandler:方法来周期性地获取加速度数据、陀螺仪数据、磁场数据。其中Xxx同样代表Accelerometer(加速度)、Gyro(陀螺仪)、Magnetometer(磁场)中任意一个。
    • ④、如果程序出现错误,或者程序想终止获取这些数据,则可调用stopXxxUpdates方法停止获取。

    例如: 
    加入头文件#import < CoreMotion/CoreMotion.h >

    1.  
      - (void)viewDidLoad {
    2.  
      [super viewDidLoad];
    3.  
      //创建CMMotionManager对象
    4.  
      self.motionManager = [[CMMotionManager alloc] init]; // ①
    5.  
      NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    6.  
      //如果CMMOtionManager支持获取加速度数据
    7.  
      if (self.motionManager.accelerometerAvailable) {
    8.  
      //设置CMMotionManager的加速度数据更新频率为0.1秒
    9.  
      self.motionManager.accelerometerUpdateInterval = 0.1;
    10.  
      //使用代码块开始获取加速度数据
    11.  
      [self.motionManager startAccelerometerUpdatesToQueue:queue withHandler:^(CMAccelerometerData *accelerometerData, NSError *error) {
    12.  
      NSString* labelText;
    13.  
      //如果发生了错误,error不为空
    14.  
      if (error) {
    15.  
      //停止获取加速度数据
    16.  
      [self.motionManager stopAccelerometerUpdates];
    17.  
      labelText = [NSString stringWithFormat:@"获取加速度数据出现错误:%@",error];
    18.  
      }else{
    19.  
      //分别获取系统在X、Y、Z轴上的加速度数据
    20.  
      labelText = [NSString stringWithFormat:@"加速度为 ------ X轴:%+.2f Y轴:%+.2f Z 轴:%+.2f",accelerometerData.acceleration.x,accelerometerData.acceleration.y,accelerometerData.acceleration.z];
    21.  
      }
    22.  
      //在主线程中更新accelerometerLabel的文本,显示加速度数据
    23.  
      [self.accelerometerLabel performSelectorOnMainThread: @selector(setText:) withObject:labelText waitUntilDone:NO];
    24.  
      }];
    25.  
      }else{
    26.  
      [self.accelerometerLabel performSelectorOnMainThread:@selector(setText:) withObject:@"该设备不支持获取加速度数据!" waitUntilDone:NO];
    27.  
      NSLog(@"该设备不支持获取加速度数据!");
    28.  
      }
    29.  
      //如果CMMotionManager的支持获取陀螺仪数据
    30.  
      if (self.motionManager.gyroAvailable) {
    31.  
      //设置CMMOtionManager的陀螺仪数据更新频率为0.1;
    32.  
      self.motionManager.gyroUpdateInterval = 0.1;
    33.  
      //使用代码块开始获取陀螺仪数据
    34.  
      [self.motionManager startGyroUpdatesToQueue:queue withHandler:^(CMGyroData *gyroData, NSError *error) {
    35.  
      NSString *labelText;
    36.  
      // 如果发生了错误,error不为空
    37.  
      if (error){
    38.  
      // 停止获取陀螺仪数据
    39.  
      [self.motionManager stopGyroUpdates];
    40.  
      labelText = [NSString stringWithFormat:@"获取陀螺仪数据出现错误: %@", error];
    41.  
      }else{
    42.  
      // 分别获取设备绕X轴、Y轴、Z轴上的转速
    43.  
      labelText = [NSString stringWithFormat: @"绕各轴的转速为 -------- X轴: %+.2f Y轴: %+.2f Z轴: %+.2f",gyroData.rotationRate.x,gyroData.rotationRate.y,gyroData.rotationRate.z];
    44.  
      }
    45.  
      // 在主线程中更新gyroLabel的文本,显示绕各轴的转速
    46.  
      [self.gyroLabel performSelectorOnMainThread:@selector(setText:)withObject:labelText waitUntilDone:NO];
    47.  
      }];
    48.  
      }else{
    49.  
      [self.gyroLabel performSelectorOnMainThread:@selector(setText:) withObject:@"该设备不支持获取陀螺仪数据!" waitUntilDone:NO];
    50.  
      }
    51.  
      //如果CMMotionManager的支持获取磁场数据
    52.  
      if (self.motionManager.magnetometerAvailable) {
    53.  
      //设置CMMotionManager的磁场数据更新频率为0.1秒
    54.  
      self.motionManager.magnetometerUpdateInterval = 0.1;
    55.  
      [self.motionManager startMagnetometerUpdatesToQueue:queue withHandler:^(CMMagnetometerData *magnetometerData, NSError *error) {
    56.  
      NSString* labelText;
    57.  
      //如果发生了错误 error不为空
    58.  
      if (error) {
    59.  
      //停止获取磁场数据
    60.  
      [self.motionManager stopMagnetometerUpdates];
    61.  
      labelText = [NSString stringWithFormat:@"获取磁场数据出现错误:%@",error];
    62.  
      }else{
    63.  
      labelText = [NSString stringWithFormat:@"磁场数据为 -------- X轴: %+.2f Y轴: %+.2f Z轴: %+.2f",magnetometerData.magneticField.x,magnetometerData.magneticField.y,magnetometerData.magneticField.z];
    64.  
      }
    65.  
      //在主线程中更新magnetometerLabel的文本,显示磁场数据
    66.  
      [self.magnetometerLabel performSelectorOnMainThread:@selector(setText:) withObject:labelText waitUntilDone:NO];
    67.  
      }];
    68.  
      }else{
    69.  
      [self.magnetometerLabel performSelectorOnMainThread:@selector(setText:) withObject:@"该设备不支持获取磁场数据!" waitUntilDone:NO];
    70.  
      }
    71.  
      }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71

    3、主动请求获取加速度数据、陀螺仪数据、磁场数据

    如果使用主动请求的方式来获取加速计数据,请按如下步骤进行:

    • ①、创建CMMotionManager对象;
    • ②、调用CMMotionManager对象的startXxxUpdates方法开始更新加速度数据、陀螺仪数据、磁场数据。其中Xxx代表Accelerometer(加速度)、Gyro(陀螺仪)和Magnetometer(磁场)中的任何一个。
    • ③、使用定时器、子线程或其他任意的额可以周期性轮询机制通过CMMotionManager对象加速度数据、陀螺仪数据、磁场数据。
    • ④、如果程序出现错误,或者程序想终止获取这些数据,则可调用stopXxxUpdates方法停止获取。 
      加入头文件 #import < CoreMotion/CoreMotion.h >
    1.  
      #import <CoreMotion/CoreMotion.h>
    2.  
      #import "ViewController.h"
    3.  
      @interface ViewController ()
    4.  
      {
    5.  
      NSTimer* updateTimer;
    6.  
      }
    7.  
      @property (strong ,nonatomic) CMMotionManager* motionManager;
    8.  
      @end
    9.  
      @implementation ViewController
    10.  
      - (void)viewWillAppear:(BOOL)animated{
    11.  
      [super viewWillAppear:animated];
    12.  
      //启动定时器来周期性地轮询加速度、陀螺仪、磁场数据
    13.  
      updateTimer = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(updateDisplay) userInfo:nil repeats:YES];
    14.  
      }
    15.  
      - (void)updateDisplay{
    16.  
      //如果CMMotionManager的加速度数据可用
    17.  
      if (self.motionManager.accelerometerAvailable) {
    18.  
      //主动请求获取加速度数据
    19.  
      CMAccelerometerData* accelerometerData = self.motionManager.accelerometerData;
    20.  
      self.accelerometerLabel.text = [NSString stringWithFormat:@"加速度为 --------- X轴:%+2.f Y轴:%+2.f Z轴:%+2.f",accelerometerData.acceleration.x,accelerometerData.acceleration.y,accelerometerData.acceleration.z];
    21.  
      }
    22.  
      if (self.motionManager.magnetometerAvailable) {
    23.  
      //如果CMMotionManager的陀螺仪数据可用
    24.  
      CMGyroData* gyroData = self.motionManager.gyroData;
    25.  
      self.gyroLabel.text = [NSString stringWithFormat:@"绕个轴的转速为 --------/nX轴:%+2.f Y轴:%+.2f Z轴:%+.2f",gyroData.rotationRate.x,gyroData.rotationRate.y,gyroData.rotationRate.z];
    26.  
      }
    27.  
      //如果CMMotionManager的磁场数据可用
    28.  
      if (self.motionManager.magnetometerAvailable) {
    29.  
      //主动请求获取磁场数据
    30.  
      CMMagnetometerData* magnetometerData = self.motionManager.magnetometerData;
    31.  
      self.magnetometerLabel.text = [NSString stringWithFormat:@"磁场数据为 --------/nX轴:%+2.f Y轴:%+.2f Z轴:%+.2f",magnetometerData.magneticField.x,magnetometerData.magneticField .y,magnetometerData.magneticField .z];
    32.  
      }
    33.  
      }
    34.  
      - (void)viewDidLoad {
    35.  
      [super viewDidLoad];
    36.  
      //创建CMMotionManager对象
    37.  
      self.motionManager = [[CMMotionManager alloc]init];
    38.  
      //如果CMMotionManager的支持获取加速度数据
    39.  
      if (self.motionManager.accelerometerAvailable) {
    40.  
      [self.motionManager startAccelerometerUpdates];
    41.  
      }else{
    42.  
      NSLog(@"该设备不支持获取加速度数据!");
    43.  
      }
    44.  
      //如果CMMotionManager的支持获取陀螺仪数据
    45.  
      if (self.motionManager.gyroAvailable) {
    46.  
      [self.motionManager startGyroUpdates];
    47.  
      }else{
    48.  
      NSLog(@"该设备不支持获取陀螺仪数据!");
    49.  
      }
    50.  
      //如果CMMotionManager的支持获取磁场数据
    51.  
      if (self.motionManager.magnetometerAvailable) {
    52.  
      [self.motionManager startMagnetometerUpdates];
    53.  
      }else{
    54.  
      NSLog(@"该设备不支持获取磁场数据!");
    55.  
      }
    56.  
      }
    57.  
      @end
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57

    实例:怪物足球 
    详情请看代码

    二、感知设备移动

    除了获取加速度数据、陀螺仪数据和磁场数据之外,CMMotionManager还可以用于感知设备移动数据。与前获取加速度数据、陀螺仪数据、磁场数据的方式完全相同,程序可通过如下两种方式来感知设备的移动数据。

    • 使用基于代码的方式获取设备移动数据;

    • 使用哪个周期性主动请求的方式获取设备移动数据;

    获取设备移动数据时,CMMotionManager将会返回一个CMDeviceMotion对象,该对象包含如下属性:

    • attitude:该属性返回设备的方位信息。该属性的分那会至是一个CMAttitude类型的对象,该对象包含roll、pitch、yaw3个欧拉角的值,通过这3个值即可获取该设备的空间方位;
    • rotationRate:该属性返回原始的陀螺仪信息,该属性值为CMRotationRate结构体变量,该属性值基本等同于前面介绍的陀螺仪数据;
    • gravity:该属性返回地球重力对该设备在X、Y、Z轴上施加的重力加速度;
    • userAcceleration:该属性返回用户外力对该设备在X、Y、Z轴上施加的重力加速度;
    • magneticField:该属性返回校准后的磁场信息。该属性值是一个CMCalibratedMagneticField结构体变量。CMCalibratedMagneticField类型的变量包括field和accuracy两个字段,其中field代表X、Y、Z、轴上的磁场强度,accuracy则代表磁场强度的精度;

    注:attitude属性是一个CMAttitude类型的变量,这种类型的变量用于表示该设备的空间方位。其中roll、pitch、yaw这3个角度的意义如下:

    • yaw角度:表示手机顶部转过的夹角。当手机绕着Z轴旋转时,该角度值发生改变。例如,当该角度为0时,表名手机并未发生旋转;该角度π/2时,代表手机逆时针转过90°;
    • pitch角度:表示手机顶部或尾部翘起的角度。当手机绕着X轴倾斜时,该角度值发生变化。该角度的取值范围是-π~π。假设将手机屏幕朝上水平放在桌子上,如果桌子是完全水平的,giant角度值应该是0。假如从手机顶部开始抬起,直到将手机沿X轴旋转180°(屏幕向下水平放在桌子上),在这个旋转过程中,该角度值会从0变化到π。也就是说没从手机顶部抬起,giant角度值会逐渐增大,直到等于π;如果从手机底部开始抬起,直到将手机沿X轴旋转180°(屏幕向下水平放在桌子上),该角度值会从0变化到-π。也就说说没从手机底部抬起,该角度值会水平放在桌面上,直到等于-π;
    • roll角度:表示手机左侧或右侧翘起的角度。当手机绕着Y轴倾斜时,该角度值发生变化。该角度的取值范围是-π/2~π/2.假设将手机屏幕朝上水平放在桌子上,如果桌子是完全水平的,该角度值应该是0。加入将手机左侧逐渐抬起,直到将手机沿Y轴旋转90°(手机与桌面垂直),在这个旋转过程中,该角度值会从0变化到π/2.也就是说,从手机左侧抬起时,该角度值会逐渐增大,直到等于π/2;如果从手机右侧开始抬起,直到将手机沿Y轴旋转90°(手机与桌面垂直),该角度值会从0变化到-π/2。也就是说,从手机右侧抬起时,该角度值会逐渐减少,直到等于-π/2;

    例如:使用CMMotionManager感知设备移动

    1.  
      - (void)viewDidLoad {
    2.  
      [super viewDidLoad];
    3.  
      //创建CMMotionManager对象
    4.  
      self.motionManager = [[CMMotionManager alloc]init];
    5.  
      //如果可以获取设备的动作信息
    6.  
      if (self.motionManager.deviceMotionAvailable) {
    7.  
      //开始更新设备的动作信息
    8.  
      [self.motionManager startDeviceMotionUpdates];
    9.  
      }else{
    10.  
      NSLog(@"该设备的deviceMotion不可用");
    11.  
      }
    12.  
      }
    13.  
      - (void)updateDisplay {
    14.  
      if (self.motionManager.deviceMotionAvailable) {
    15.  
      //获取设备移动信息
    16.  
      CMDeviceMotion* deviceMotion = self.motionManager.deviceMotion;
    17.  
      NSMutableString* str = [NSMutableString stringWithString:@"deviceMotion信息为: "];
    18.  
      [str appendFormat:@"---attitude信息--- "];
    19.  
      [str appendFormat:@"attitude的yaw:%+.2f ",deviceMotion.attitude.yaw];
    20.  
      [str appendFormat:@"attitude的pitch:%+.2f " , deviceMotion.attitude.pitch];
    21.  
      [str appendFormat:@"attitude的roll:%+.2f " , deviceMotion.attitude.roll];
    22.  
      [str appendString:@"---rotationRate信息--- "];
    23.  
      [str appendFormat:@"rotationRate的X:%+.2f ", deviceMotion.rotationRate.x];
    24.  
      [str appendFormat:@"rotationRate的Y:%+.2f " , deviceMotion.rotationRate.y];
    25.  
      [str appendFormat:@"rotationRate的Z:%+.2f " , deviceMotion.rotationRate.z];
    26.  
      [str appendString:@"---gravity信息--- "];
    27.  
      [str appendFormat:@"gravity的X:%+.2f ", deviceMotion.gravity.x];
    28.  
      [str appendFormat:@"gravity的Y:%+.2f " , deviceMotion.gravity.y];
    29.  
      [str appendFormat:@"gravity的Z:%+.2f " , deviceMotion.gravity.z];
    30.  
      [str appendString:@"---magneticField信息--- "];
    31.  
      [str appendFormat:@"magneticField的精度:%d ",
    32.  
      deviceMotion.magneticField.accuracy];
    33.  
      [str appendFormat:@"magneticField的X:%+.2f ",
    34.  
      deviceMotion.magneticField.field.x];
    35.  
      [str appendFormat:@"magneticField的Y:%+.2f " ,
    36.  
      deviceMotion.magneticField.field.y];
    37.  
      [str appendFormat:@"magneticField的Z:%+.2f " ,
    38.  
      deviceMotion.magneticField.field.z];
    39.  
      self.showField.text = str;
    40.  
      }
    41.  
      }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    实例:水平仪 
    详情请看代码

    三、iOS 7新增的计步器

    iOS 7新增的CMStepCounter作为计步器,该计步器可以获取用户携带该设备行走的步数,iOS设备通过内置硬件来手机并存储用户行走的步数。程序通过该类即可获取用户当前行走的步数,也可查询用户行走的历史活动数据。

    CMStepCounter提供了isStepCountingAvailable类方法来判断计步器是否可用,在传统的iPhone、iPad设备上,CMStepCounter暂时不可用。

    使用CMStepCounter获取实时的计步数据可通过如下方法: 
    ①、

    - (void)startStepCountingUpdatesToQueue:(NSOperationQueue *)queue updateOn:(NSInteger)stepCounts withHandler:(CMStepUpdateHandler)handler;
    • 1

    该方法的第一个参数需要一个NSOperationQueue对象,第二个参数指定用户每行行走多少步才执行第三个代码块参数一次。比如将第二个参数指定为100,则表明用户行走200、300、400…步时踩执行第三个代码块参数。第三个参数是一个形如^^(NSInteger numberOfSteps,NSDate *timestamp,NSError *error){}代码块,该代码块中的numberOfSteps参数代表用户当前行走的步数; 
    ②、

    - (void)stopStepCountingUpdates;
    • 1

    程序停止计步; 
    ③、

    - (void)queryStepCountStartingFrom:(NSDate *)start to:(NSDate *)end toQueue:(NSOperationQueue *)queue withHandler:(CMStepQueryHandler)handler;
    • 1

    如果程序希望通过CMStepCounter查询历史数据,则可调用该方法;该方法的前两个参数用于指定获取哪一个时间段的步数信息。

    注意:iOS 8用 CMPedometer代替。 
    iOS 8新增的CMPedometer代替iOS 7的CMStepCounter作为计步器,该计步器可以获取用户携带该设备行走的步数。该类包含如下几个方法:

    ①、

    + (BOOL)isStepCountingAvailable;
    • 1

    该方法跟CMStepCounter一样,判断计步服务是否可用; 
    ②、

    + (BOOL)isDistanceAvailable;
    • 1

    判断计算距离是否可用;

    ③、

    + (BOOL)isFloorCountingAvailable;
    • 1

    判断计算层楼测量是否可用; 
    ④、

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

    该方法进行实时测量,第一个参数是指进行实时测量的开始时间;第二个参数是block ^(CMPedometerData *pedometerData, NSError *error);其中pedometerData为测量数据,error为测量错误信息。 
    ⑤、

    - (void)stopPedometerUpdates;
    • 1

    停止计步服务; 
    ⑥、

    - (void)queryPedometerDataFromDate:(NSDate *)start toDate:(NSDate *)end withHandler:(CMPedometerHandler)handler;
    • 1

    第一个参数为开始时间;第二个参数为结束时间;第三个参数为block^(CMPedometerData *pedometerData, NSError *error);其中pedometerData为测量数据,error为测量错误信息。

    测量数据:CMPedometerData属性如下:

    ①、

    @property(readonly, nonatomic) NSDate *startDate;
    • 1

    统计开始时间; 
    ②、

    @property(readonly, nonatomic) NSDate *endDate;
    • 1

    统计结束时间; 
    ③、

    @property(readonly, nonatomic) NSNumber *numberOfSteps;
    • 1

    步数; 
    ④、

    @property(readonly, nonatomic) NSNumber *distance;
    • 1

    推算距离; 
    ⑤、

    @property(readonly, nonatomic) NSNumber *floorsAscended;
    • 1

    上升的楼层数; 
    ⑥、

    @property(readonly, nonatomic) NSNumber *floorsDescended;
    • 1

    下降的楼层数;

    例如: 
    加入头文件 #import < CoreMotion/CoreMotion.h >

    iOS 7下获取步数< CMStepCounter >

    1.  
      - (void)viewDidLoad {
    2.  
      [super viewDidLoad];
    3.  
      //如果计步服务可用
    4.  
      if ([CMStepCounter isStepCountingAvailable]) {
    5.  
      //创建CMStepCounter对象
    6.  
      self.stepCounter = [[CMStepCounter alloc]init];
    7.  
      NSOperationQueue* queue = [[NSOperationQueue alloc]init];
    8.  
      //开始收集计步信息,设置每行走5步执行一次代码块
    9.  
      [self.stepCounter startStepCountingUpdatesToQueue:queue updateOn:5 withHandler:^(NSInteger numberOfSteps, NSDate *timestamp, NSError *error) {
    10.  
      self.stepLabel.text = [NSString stringWithFormat:@"用户已经行走了【%ld】步",numberOfSteps];
    11.  
      }];
    12.  
      }else{
    13.  
      self.stepLabel.text = @"计步器不可用。";
    14.  
      }
    15.  
      }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    iOS 8下获取步数< CMPedometer >

    1.  
      - (void)viewDidLoad {
    2.  
      [super viewDidLoad];
    3.  
      //如果计步服务可用
    4.  
      if ([CMPedometer isStepCountingAvailable]) {
    5.  
      self.pedometer = [[CMPedometer alloc] init];
    6.  
      [self.pedometer startPedometerUpdatesFromDate:[NSDate date] withHandler:^(CMPedometerData *pedometerData, NSError *error) {
    7.  
      self.stepLabel.text = [NSString stringWithFormat:@"用户已经行走了【%@】步",pedometerData.numberOfSteps];
    8.  
      }];
    9.  
      }
    10.  
      }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    四、iOS 7新增的CMMotionActivityManager

    iOS新增了CMMotionActivityManager来收集、存储用户的运动数据——此处的运动数据用于反映用户当前处于步行、跑步、驾驶车辆或处于静止状态。对于导航应用而言,可通过该类获取用于当前的运动类型的改变,并根据不同的运动类型提供更精确的导航。

    通过CMMotionActivityManager类,应用程序即可获取用户当前的运动数据,也可查询用户在过去某个时间段的运动数据。

    CMMotionActivityManager提供了isActivityAvailable类方法来判断获取运动数据是否可用,在传统的iPhone、iPad设备上,CMMotionActivityManager暂时不可用。

    使用CMMotionAcvitityManager获取实时的运动数据可通过如下方法:

    ①、

    - (void)startActivityUpdatesToQueue:(NSOperationQueue *)queue withHandler:(CMMotionActivityHandler)handler;
    • 1

    该方法的第一个参数需要传一个NSOperationQueue对象;第二个参数是一个形如^(CMMotionActivity *activity){}的代码块,该代码块中的CMMotionActivityManager参数代表用户当前的运动数据; 
    ②、

    - (void)stopActivityUpdates;
    • 1

    该方法用于停止获取运动数据; 
    ③、

    - (void)queryActivityStartingFromDate:(NSDate *)start toDate:(NSDate *)end toQueue:(NSOperationQueue *)queue withHandler:(CMMotionActivityQueryHandler)handler;
    • 1

    该方法用于查询历史数据,前面两个从哪回溯用于指定获取那个时间段的运动数据;

    通过CMMotionActivityManager获取运动数据时,程序将会得到一个CMMotionActivity对象,该对象包含如下属性:

    ①、

    @property(readonly, nonatomic) BOOL stationary;
    • 1

    该属性返回用户是否处于静止状态; 
    ②、

    @property(readonly, nonatomic) BOOL walking;
    • 1

    该属性返回用户是否正在步行; 
    ③、

    @property(readonly, nonatomic) BOOL running;
    • 1

    该属性返回用户是否正在跑步; 
    ④、

    @property(readonly, nonatomic) BOOL automotive;
    • 1

    该属性返回用户是否正在驾车; 
    ⑤、

    @property(readonly, nonatomic) BOOL unknown;
    • 1

    该属性返回用户是否处于未知运动中; 
    ⑥、

    @property(readonly, nonatomic) NSDate *startDate;
    • 1

    获取该运动的开始时间; 
    ⑦、

    @property(readonly, nonatomic) CMMotionActivityConfidence confidence;
    • 1

    该属性返回该运动数据的可靠程度;

    例如:加入头文件 #import < CoreMotion/CoreMotion.h >

    1.  
      - (void)viewDidLoad {
    2.  
      [super viewDidLoad];
    3.  
      //如果设备支持获取运动数据
    4.  
      if(CMMotionActivityManager.isActivityAvailable) {
    5.  
      //创建CMMotionActivityManager对象
    6.  
      self.motionActivityManager = [[CMMotionActivityManager alloc]init];
    7.  
      NSOperationQueue* queue = [[NSOperationQueue alloc]init];
    8.  
      //开始收集运动数据,当收集到运动信息时执行传给该方法的代码块参数
    9.  
      [self.motionActivityManager startActivityUpdatesToQueue:queue withHandler:^(CMMotionActivity *activity) {
    10.  
      NSMutableString* str = [NSMutableString stringWithFormat:@"---运动信息--- "];
    11.  
      //获取运动信息
    12.  
      [str appendFormat:@"是否步行:%d ",activity.walking];
    13.  
      [str appendFormat:@"是否跑步:%d ",activity.running];
    14.  
      [str appendFormat:@"是否驾车:%d ",activity.automotive];
    15.  
      [str appendFormat:@"是否静止:%d ",activity.stationary];
    16.  
      [str appendFormat:@"是否未知:%d ",activity.unknown];
    17.  
      self.activityLabel.text = str;
    18.  
      }];
    19.  
      }else{
    20.  
      self.activityLabel.text = @"该设备不支持获取运动数据";
    21.  
      }
    22.  
      }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
  • 相关阅读:
    CCF CSP 题解
    CCF CSP 2019032 二十四点
    CCF CSP 2018121 小明上学
    CCF CSP 2019092 小明种苹果(续)
    CCF CSP 2019091 小明种苹果
    CCF CSP 2019121 报数
    CCF CSP 2019031 小中大
    CCF CSP 2020061 线性分类器
    CCF CSP 2020062 稀疏向量
    利用国家气象局的webservice查询天气预报(转载)
  • 原文地址:https://www.cnblogs.com/itlover2013/p/14235497.html
Copyright © 2011-2022 走看看