• 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
  • 相关阅读:
    聊聊软件架构
    聊聊Docker
    segment fault异常及常见定位手段
    Linux设备驱动故障定位指引与实例
    C语言switch/case圈复杂度优化重构
    Linux设备驱动框架设计
    TLA+和并发系统正确性验证
    linux kexec内核引导
    Linux中断子系统:级联中断控制器驱动
    软件性能优化方法汇编
  • 原文地址:https://www.cnblogs.com/itlover2013/p/14235497.html
Copyright © 2020-2023  润新知