iOS开发之CoreMotion框架的应用
我们知道,现在智能手机手机的功能已经越来越强大。小小的手机中集成了众多的传感器配件。通过这些传感器可以获取到手机甚至用户的状态信息。
在iOS5之前,加速度传感器的相关信息封装在UIAccelerometer这个类中,其主要用来获取设备在三维空间中的状态信息,之后,加速度传感器以及螺旋仪传感器的相关信息都封装在了CoreMotion这个框架中,这个框架对加速度,磁力以及螺旋仪传感器信息进行统一管理,并封装了许多强大的计算方法帮助开发者获取设备的空间状态。
之前有写过一篇关于UIAccelerometer与CoreMotion简单使用的博客,比较偏用法介绍,并不系统,本篇博客是针对CoreMotion的完善与补充。
https://my.oschina.net/u/2340880/blog/543434
一、CoreMotion框架整体结构
在学习这个框架之前,首先需要对框架中类的关系与作用有个整体的了解。下图展示了CoreMotion框架的整体结构:
从上图中可以看出,CoreMotion框架中主要分为3大块,一部分是用来获取设备的运动状态,如速度,加速度,海拔,三维方向等。一部分是用来配合iWatch进行用户的运动状态获取、另一部分为用户步数相关接口。
二、CMMotionManager
CMMotionManager类是CoreMotion框架中非常核心的一个类,其用来进行设备运动信息的整体管理。主要包括开启更新信息,停止更新信息,获取更新信息等。解析如下:
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
| @property(readonly, nonatomic, getter=isAccelerometerAvailable) BOOL accelerometerAvailable;
@property(assign, nonatomic) NSTimeInterval accelerometerUpdateInterval;
@property(readonly, nonatomic, getter=isAccelerometerActive) BOOL accelerometerActive;
@property(readonly, nullable) CMAccelerometerData *accelerometerData;
- (void)startAccelerometerUpdates;
- (void)startAccelerometerUpdatesToQueue:(NSOperationQueue *)queue withHandler:(CMAccelerometerHandler)handler;
- (void)stopAccelerometerUpdates;
@property(readonly, nonatomic, getter=isGyroAvailable) BOOL gyroAvailable;
@property(assign, nonatomic) NSTimeInterval gyroUpdateInterval;
@property(readonly, nonatomic, getter=isGyroActive) BOOL gyroActive;
@property(readonly, nullable) CMGyroData *gyroData;
- (void)startGyroUpdates;
- (void)startGyroUpdatesToQueue:(NSOperationQueue *)queue withHandler:(CMGyroHandler)handler;
- (void)stopGyroUpdates;
@property(readonly, nonatomic, getter=isMagnetometerAvailable) BOOL magnetometerAvailable;
@property(assign, nonatomic) NSTimeInterval magnetometerUpdateInterval;
@property(readonly, nonatomic, getter=isMagnetometerActive) BOOL magnetometerActive;
@property(readonly, nullable) CMMagnetometerData *magnetometerData;
- (void)startMagnetometerUpdates;
- (void)startMagnetometerUpdatesToQueue:(NSOperationQueue *)queue withHandler:(CMMagnetometerHandler)handler;
- (void)stopMagnetometerUpdates;
@property(readonly, nonatomic, getter=isDeviceMotionAvailable) BOOL deviceMotionAvailable;
@property(assign, nonatomic) NSTimeInterval deviceMotionUpdateInterval;
@property(readonly, nonatomic, getter=isDeviceMotionActive) BOOL deviceMotionActive;
@property(readonly, nullable) CMDeviceMotion *deviceMotion;
- (void)startDeviceMotionUpdates;
- (void)startDeviceMotionUpdatesToQueue:(NSOperationQueue *)queue withHandler:(CMDeviceMotionHandler)handler;
- (void)stopDeviceMotionUpdates;
|
上面的方法看上去非常繁多,其实很有规律,总的来说就是对是否开启传感器数据进行管理,并且进行传感器数据的获取。下面我们来看几种具体的传感器数据类的定义。
三、数据模型类
首先,CoreMotion框架中的数据模型类都继承自CMLogItem类,这个类里面只有一个属性:
1 2 3
| @interface CMLogItem : NSObject <NSSecureCoding, NSCopying> @property(readonly, nonatomic) NSTimeInterval timestamp; @end
|
CMLogItem类的timestamp属性用来标记数据记录的时间戳。
1.加速计数据
CMAccelerometerData是加速计数据的数据模型类:
1 2 3 4 5 6 7 8 9 10
| @interface CMAccelerometerData : CMLogItem
@property(readonly, nonatomic) CMAcceleration acceleration; @end
typedef struct { double x; double y; double z; } CMAcceleration;
|
2、陀螺仪数据
CMGyroData是陀螺仪数据的数据模型类:
1 2 3 4 5 6 7 8 9 10 11
| @interface CMGyroData : CMLogItem
@property(readonly, nonatomic) CMRotationRate rotationRate; @end
typedef struct { double x; double y; double z; } CMRotationRate;
|
3.磁强计数据
CMMagnetometerData是磁强计数据模型类:
1 2 3 4 5 6 7 8 9 10 11 12
| @interface CMMagnetometerData : CMLogItem {
@property(readonly, nonatomic) CMMagneticField magneticField;
@end
typedef struct { double x; double y; double z; } CMMagneticField;
|
4.设备运动信息
CMDeviceMotion类包含了设备的空间状态信息:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| @interface CMDeviceMotion : CMLogItem
@property(readonly, nonatomic) CMAttitude *attitude;
@property(readonly, nonatomic) CMRotationRate rotationRate;
@property(readonly, nonatomic) CMAcceleration gravity;
@property(readonly, nonatomic) CMAcceleration userAcceleration;
@property(readonly, nonatomic) CMCalibratedMagneticField magneticField;
@property(readonly, nonatomic) double heading; @end
|
CMCalibratedMagneticField是一个结构体,如下:
1 2 3 4 5 6 7 8 9 10 11
| typedef struct { CMMagneticField field; CMMagneticFieldCalibrationAccuracy accuracy; } CMCalibratedMagneticField;
typedef NS_ENUM(int, CMMagneticFieldCalibrationAccuracy) { CMMagneticFieldCalibrationAccuracyUncalibrated = -1, CMMagneticFieldCalibrationAccuracyLow, CMMagneticFieldCalibrationAccuracyMedium, CMMagneticFieldCalibrationAccuracyHigh } ;
|
CMAttitude类中封装的信息如下:
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
| @interface CMAttitude : NSObject <NSCopying, NSSecureCoding> {
@property(readonly, nonatomic) double roll;
@property(readonly, nonatomic) double pitch;
@property(readonly, nonatomic) double yaw;
@property(readonly, nonatomic) CMRotationMatrix rotationMatrix;
@property(readonly, nonatomic) CMQuaternion quaternion;
- (void)multiplyByInverseOfAttitude:(CMAttitude *)attitude;
@end
typedef struct { double x, y, z, w; } CMQuaternion;
typedef struct { double m11, m12, m13; double m21, m22, m23; double m31, m32, m33; } CMRotationMatrix;
|
四、高度信息
CoreMotion框架中的CMAltimeter类提供对设备高度相关信息的数据支持,这个类是iOS 8后新加入的,CMAltimeter类解析如下:
1 2 3 4 5 6 7 8 9 10
| @interface CMAltimeter : NSObject
+ (BOOL)isRelativeAltitudeAvailable;
+ (CMAuthorizationStatus)authorizationStatus;
- (void)startRelativeAltitudeUpdatesToQueue:(NSOperationQueue *)queue withHandler:(CMAltitudeHandler)handler;
- (void)stopRelativeAltitudeUpdates; @end
|
CMAltitudeData是高度信息数据:
1 2 3 4 5 6
| @interface CMAltitudeData : CMLogItem
@property(readonly, nonatomic) NSNumber *relativeAltitude;
@property(readonly, nonatomic) NSNumber *pressure; @end
|
五、用户活动信息
CMMotionActivityManager类是iOS 7之后新引入到CoreMotion框架中的,这个类用来对用户的活动信息进行管理,解析如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| @interface CMMotionActivityManager : NSObject
+ (BOOL)isActivityAvailable;
+ (CMAuthorizationStatus)authorizationStatus;
- (void)queryActivityStartingFromDate:(NSDate *)start toDate:(NSDate *)end toQueue:(NSOperationQueue *)queue withHandler:(CMMotionActivityQueryHandler)handler;
- (void)startActivityUpdatesToQueue:(NSOperationQueue *)queue withHandler:(CMMotionActivityHandler)handler;
- (void)stopActivityUpdates; @end
|
CMMotionActivity是用户活动信息的具体记录:
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
| @interface CMMotionActivity : CMLogItem
@property(readonly, nonatomic) CMMotionActivityConfidence confidence;
@property(readonly, nonatomic) NSDate *startDate;
@property(readonly, nonatomic) BOOL unknown;
@property(readonly, nonatomic) BOOL stationary;
@property(readonly, nonatomic) BOOL walking;
@property(readonly, nonatomic) BOOL running;
@property(readonly, nonatomic) BOOL automotive;
@property(readonly, nonatomic) BOOL cycling; @end
|
六、用户手臂动作分析
在iOS 12系统后,CoreMotion框架中又引入了一些列配合iWatch进行用户手臂动作分析的类,可以分析出用户是否发生了运动障碍等。其主要由CMMovementDisorderManager类进行管理,如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| @interface CMMovementDisorderManager : NSObject
+ (BOOL)isAvailable;
+ (CMAuthorizationStatus)authorizationStatus;
- (void)monitorKinesiasForDuration:(NSTimeInterval)duration;
- (void)queryDyskineticSymptomFromDate:(NSDate *)fromDate toDate:(NSDate *)toDate withHandler:(CMDyskineticSymptomResultHandler)handler;
- (void)queryTremorFromDate:(NSDate *)fromDate toDate:(NSDate *)toDate withHandler:(CMTremorResultHandler)handler;
- (NSDate * _Nullable)lastProcessedDate;
- (NSDate * _Nullable)monitorKinesiasExpirationDate; @end
|
CMDyskineticSymptomResult运动障碍数据模型:
1 2 3 4 5 6 7 8 9 10
| @interface CMDyskineticSymptomResult : NSObject <NSCopying, NSSecureCoding>
@property (copy, nonatomic, readonly) NSDate *startDate;
@property (copy, nonatomic, readonly) NSDate *endDate;
@property (nonatomic, readonly) float percentUnlikely;
@property (nonatomic, readonly) float percentLikely; @end
|
CMTremorResult记录用户震颤数据:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| @interface CMTremorResult : NSObject <NSCopying, NSSecureCoding>
@property (copy, nonatomic, readonly) NSDate *startDate;
@property (copy, nonatomic, readonly) NSDate *endDate;
@property (nonatomic, readonly) float percentUnknown;
@property (nonatomic, readonly) float percentNone;
@property (nonatomic, readonly) float percentSlight;
@property (nonatomic, readonly) float percentMild;
@property (nonatomic, readonly) float percentModerate;
@property (nonatomic, readonly) float percentStrong;
|
七、计步器应用
在iOS 8之后,CoreMotion中引入了CMPedometer相关计步器类,这些类封装的更加应用层,开发者可以直接获取用户步数相关数据,CMPedometer是管理类,解析如下:
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
| @interface CMPedometer : NSObject
+ (BOOL)isStepCountingAvailable;
+ (BOOL)isDistanceAvailable;
+ (BOOL)isFloorCountingAvailable;
+ (BOOL)isPaceAvailable;
+ (BOOL)isCadenceAvailable;
+ (BOOL)isPedometerEventTrackingAvailable;
+ (CMAuthorizationStatus)authorizationStatus;
- (void)queryPedometerDataFromDate:(NSDate *)start toDate:(NSDate *)end withHandler:(CMPedometerHandler)handler;
- (void)startPedometerUpdatesFromDate:(NSDate *)start withHandler:(CMPedometerHandler)handler;
- (void)stopPedometerUpdates;
- (void)startPedometerEventUpdatesWithHandler:(CMPedometerEventHandler)handler;
- (void)stopPedometerEventUpdates; @end
|
CMPedometerEvent类记录计步器的事件变化:
1 2 3 4 5 6 7 8 9 10 11
| @interface CMPedometerEvent : NSObject <NSSecureCoding, NSCopying>
@property(readonly, nonatomic) NSDate *date;
@property(readonly, nonatomic) CMPedometerEventType type; @end
|
CMPedometerData计步器数据类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| @interface CMPedometerData
@property(readonly, nonatomic) NSDate *startDate;
@property(readonly, nonatomic) NSDate *endDate;
@property(readonly, nonatomic) NSNumber *numberOfSteps;
@property(readonly, nonatomic, nullable) NSNumber *distance;
@property(readonly, nonatomic, nullable) NSNumber *floorsAscended;
@property(readonly, nonatomic, nullable) NSNumber *floorsDescended;
@property(readonly, nonatomic, nullable) NSNumber *currentPace;
@property(readonly, nonatomic, nullable) NSNumber *currentCadence;
@property(readonly, nonatomic, nullable) NSNumber *averageActivePace; @end
|
在CoreMotion中,CMStepCounter也是一个记录器类,其比较简易,只在iOS8之前进行使用,解析如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| @interface CMStepCounter : NSObject
+ (BOOL)isStepCountingAvailable;
- (void)queryStepCountStartingFrom:(NSDate *)start to:(NSDate *)end toQueue:(NSOperationQueue *)queue withHandler:(CMStepQueryHandler)handler;
- (void)startStepCountingUpdatesToQueue:(NSOperationQueue *)queue updateOn:(NSInteger)stepCounts withHandler:(CMStepUpdateHandler)handler;
- (void)stopStepCountingUpdates; @end
|