咱們知道,如今智能手機手機的功能已經愈來愈強大。小小的手機中集成了衆多的傳感器配件。經過這些傳感器能夠獲取到手機甚至用戶的狀態信息。數據結構
在iOS5以前,加速度傳感器的相關信息封裝在UIAccelerometer這個類中,其主要用來獲取設備在三維空間中的狀態信息,以後,加速度傳感器以及螺旋儀傳感器的相關信息都封裝在了CoreMotion這個框架中,這個框架對加速度,磁力以及螺旋儀傳感器信息進行統一管理,並封裝了許多強大的計算方法幫助開發者獲取設備的空間狀態。框架
以前有寫過一篇關於UIAccelerometer與CoreMotion簡單使用的博客,比較偏用法介紹,並不系統,本篇博客是針對CoreMotion的完善與補充。dom
http://www.javashuo.com/article/p-wokdhoar-em.htmlide
在學習這個框架以前,首先須要對框架中類的關係與做用有個總體的瞭解。下圖展現了CoreMotion框架的總體結構:函數
從上圖中能夠看出,CoreMotion框架中主要分爲3大塊,一部分是用來獲取設備的運動狀態,如速度,加速度,海拔,三維方向等。一部分是用來配合iWatch進行用戶的運動狀態獲取、另外一部分爲用戶步數相關接口。學習
CMMotionManager類是CoreMotion框架中很是核心的一個類,其用來進行設備運動信息的總體管理。主要包括開啓更新信息,中止更新信息,獲取更新信息等。解析以下:atom
//獲取加速計是否可用 @property(readonly, nonatomic, getter=isAccelerometerAvailable) BOOL accelerometerAvailable; //加速計更新間隔 @property(assign, nonatomic) NSTimeInterval accelerometerUpdateInterval; //加速計是否在持續進行更新 @property(readonly, nonatomic, getter=isAccelerometerActive) BOOL accelerometerActive; //最後一次更新的加速計信息 CMAccelerometerData後面會介紹 @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; //設備運動數據並不是某個傳感器的數據 而是上面3種傳感器數據的組合與運算 //設備運動數據是否可用 @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;
上面的方法看上去很是繁多,其實頗有規律,總的來講就是對是否開啓傳感器數據進行管理,而且進行傳感器數據的獲取。下面咱們來看幾種具體的傳感器數據類的定義。spa
首先,CoreMotion框架中的數據模型類都繼承自CMLogItem類,這個類裏面只有一個屬性:.net
@interface CMLogItem : NSObject <NSSecureCoding, NSCopying> @property(readonly, nonatomic) NSTimeInterval timestamp; @end
CMLogItem類的timestamp屬性用來標記數據記錄的時間戳。線程
CMAccelerometerData是加速計數據的數據模型類:
@interface CMAccelerometerData : CMLogItem //加速計數據 @property(readonly, nonatomic) CMAcceleration acceleration; @end //加速計數據結構體 typedef struct { double x; //x方向加速度 double y; //y方向加速度 double z; //z方向加速度 } CMAcceleration;
CMGyroData是陀螺儀數據的數據模型類:
@interface CMGyroData : CMLogItem //角速度數據 @property(readonly, nonatomic) CMRotationRate rotationRate; @end //角速度結構體 typedef struct { double x; //x方向的角速度 double y; //y方向的角速度 double z; //z方向的角速度 } CMRotationRate;
CMMagnetometerData是磁強計數據模型類:
@interface CMMagnetometerData : CMLogItem { //磁強數據 @property(readonly, nonatomic) CMMagneticField magneticField; @end typedef struct { double x; //x軸磁場 double y; //y軸磁場 double z; //z軸磁場 } CMMagneticField;
CMDeviceMotion類包含了設備的空間狀態信息:
@interface CMDeviceMotion : CMLogItem //設備的空間狀態 CMAttitude後面會介紹 @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是一個結構體,以下:
typedef struct { CMMagneticField field; //磁場 CMMagneticFieldCalibrationAccuracy accuracy; //磁場強度 } CMCalibratedMagneticField; typedef NS_ENUM(int, CMMagneticFieldCalibrationAccuracy) { CMMagneticFieldCalibrationAccuracyUncalibrated = -1, CMMagneticFieldCalibrationAccuracyLow, //低 CMMagneticFieldCalibrationAccuracyMedium,//中 CMMagneticFieldCalibrationAccuracyHigh//高 } ;
CMAttitude類中封裝的信息以下:
@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類解析以下:
@interface CMAltimeter : NSObject //是否支持相對高度變化 + (BOOL)isRelativeAltitudeAvailable; //進行用戶權限的申請 + (CMAuthorizationStatus)authorizationStatus; //開始更新高度變化信息數據 - (void)startRelativeAltitudeUpdatesToQueue:(NSOperationQueue *)queue withHandler:(CMAltitudeHandler)handler; //中止更新高度變化信息數據 - (void)stopRelativeAltitudeUpdates; @end
CMAltitudeData是高度信息數據:
@interface CMAltitudeData : CMLogItem //相對高度 單位爲米 @property(readonly, nonatomic) NSNumber *relativeAltitude; //壓力 單位爲千帕 @property(readonly, nonatomic) NSNumber *pressure; @end
CMMotionActivityManager類是iOS 7以後新引入到CoreMotion框架中的,這個類用來對用戶的活動信息進行管理,解析以下:
@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是用戶活動信息的具體記錄:
@interface CMMotionActivity : CMLogItem //數據的可信度 /* typedef NS_ENUM(NSInteger, CMMotionActivityConfidence) { CMMotionActivityConfidenceLow = 0, //可信度低 CMMotionActivityConfidenceMedium, //可信度中 CMMotionActivityConfidenceHigh //可信度高 }; */ @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類進行管理,以下:
@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運動障礙數據模型:
@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記錄用戶震顫數據:
@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是管理類,解析以下:
@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類記錄計步器的事件變化:
@interface CMPedometerEvent : NSObject <NSSecureCoding, NSCopying> //記錄數據的時間 @property(readonly, nonatomic) NSDate *date; /* typedef NS_ENUM(NSInteger, CMPedometerEventType) { CMPedometerEventTypePause, //計步器暫停 CMPedometerEventTypeResume //計步器恢復 } */ @property(readonly, nonatomic) CMPedometerEventType type; @end
CMPedometerData計步器數據類:
@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以前進行使用,解析以下:
@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