版本記錄
版本號(hào) | 時(shí)間 |
---|---|
V1.0 | 2017.08.05 |
前言
我們的app很多都需要獲取使用者的動(dòng)作宗侦、方向以及其他和方位或者位置有關(guān)的參數(shù),在ios中對(duì)應(yīng)的框架就是
CoreMotion
,而在硬件對(duì)應(yīng)的就是集成的加速計(jì)和陀螺儀蚤霞。這幾篇我們就從基礎(chǔ)原理理論出發(fā)镣煮,講一下相關(guān)的知識(shí)奈搜。關(guān)于這個(gè)框架的了解感興趣的可以看這幾篇悉盆。
1. CoreMotion框架(一)—— 基礎(chǔ)理論
功能要求
前面我寫過(guò)兩篇文章關(guān)于橫豎屏適配的問(wèn)題,就是根據(jù)設(shè)備方向等進(jìn)行適配的馋吗。這里我要說(shuō)另外一種方法焕盟,就是利用CoreMotion
框架和加速器獲取設(shè)備的方向進(jìn)行適配的。
功能實(shí)現(xiàn)
使用加速器宏粤,ios5
是一個(gè)分界線脚翘。
- 在
iOS4
以前:使用UIAccelerometer
,用法非常簡(jiǎn)單(到了iOS5就已經(jīng)過(guò)期)绍哎,雖然過(guò)期但是現(xiàn)在仍然可以用来农。 - 從
iOS4
開始:CoreMotion.framework
。
1. iOS5以前
iOS5
以前使用的是類UIAccelerometer
崇堰,它屬于UIKit
框架里面的沃于。
1. JJAccelerometerVC.m
#import "JJAccelerometerVC.h"
@interface JJAccelerometerVC () <UIAccelerometerDelegate>
@end
@implementation JJAccelerometerVC
#pragma mark - Override Base Function
- (void)viewDidLoad
{
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
UIAccelerometer *acclerometer = [UIAccelerometer sharedAccelerometer];
acclerometer.updateInterval = 1.0/15;
acclerometer.delegate = self;
}
#pragma mark - UIAccelerometerDelegate
- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration
{
UIAccelerationValue x = acceleration.x;
UIAccelerationValue y = acceleration.y;
UIAccelerationValue z = acceleration.z;
if (fabs(x) <= fabs(y)) {
if (y >= 0) {
NSLog(@"UIDeviceOrientationPortraitUpsideDown");
}
else {
NSLog(@"UIDeviceOrientationPortrait");
}
}
else {
if (x >= 0) {
NSLog(@"UIDeviceOrientationLandscapeRight");
}
else {
NSLog(@"UIDeviceOrientationLandscapeLeft");
}
}
}
@end
這里,采樣頻率為1s15
次海诲,所以輸出的很快繁莹。給大家隨便粘出來(lái)幾個(gè)輸出值。
2017-08-05 18:00:44.555400+0800 JJOC[7804:3020881] UIDeviceOrientationPortrait
2017-08-05 18:00:44.622714+0800 JJOC[7804:3020881] UIDeviceOrientationLandscapeRight
2017-08-05 18:00:44.689951+0800 JJOC[7804:3020881] UIDeviceOrientationPortrait
2017-08-05 18:00:44.757171+0800 JJOC[7804:3020881] UIDeviceOrientationLandscapeRight
2017-08-05 18:00:44.824398+0800 JJOC[7804:3020881] UIDeviceOrientationPortrait
2017-08-05 18:00:44.891813+0800 JJOC[7804:3020881] UIDeviceOrientationPortrait
2017-08-05 18:00:44.958975+0800 JJOC[7804:3020881] UIDeviceOrientationPortrait
2017-08-05 18:00:45.026187+0800 JJOC[7804:3020881] UIDeviceOrientationPortrait
2. iOS5以后
加速計(jì)和陀螺儀的值都是通過(guò)Core Motion
框架訪問(wèn)的特幔,應(yīng)用程序創(chuàng)建一個(gè)CMMotionManager
實(shí)例咨演,然后通過(guò)以下某種模式使用它:
- 可以在動(dòng)作發(fā)生時(shí)執(zhí)行一些代碼。
- 可以時(shí)刻監(jiān)視一個(gè)持續(xù)更新的結(jié)構(gòu)蚯斯,是你隨時(shí)能夠訪問(wèn)到最新的值薄风。
對(duì)于數(shù)據(jù)的獲取和處理,也有兩種方式溉跃,一種是pull
村刨,另外一種是push
。
- push :實(shí)時(shí)采集所有數(shù)據(jù)(時(shí)刻監(jiān)視撰茎,采集頻率高),這個(gè)是框架按照一定的采用頻率自動(dòng)返回的打洼,具體多上時(shí)間發(fā)update一次龄糊,就看你怎么設(shè)置了。
- pull :在有需要的時(shí)候募疮,再主動(dòng)去采集數(shù)據(jù)(基于事件的動(dòng)作)炫惩。這個(gè)就看開發(fā)者什么時(shí)候調(diào)用什么時(shí)候就會(huì)返回一次,框架不會(huì)主動(dòng)給返回阿浓。
在ios5
以后他嚷,我們看下面代碼。
push
//push
1. JJGravityVC.m
#import "JJGravityVC.h"
#import <CoreMotion/CoreMotion.h>
@interface JJGravityVC ()
@property (nonatomic, assign) NSTimeInterval updateInterval;
@property (nonatomic, strong) CMMotionManager *motionManager;
@end
@implementation JJGravityVC
#pragma mark - Override Base Function
- (void)viewDidLoad
{
[super viewDidLoad];
self.view.backgroundColor = [UIColor greenColor];
self.updateInterval = 1.0/15.0;
self.motionManager = [[CMMotionManager alloc] init];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
if ([self.motionManager isAccelerometerAvailable]) {
self.motionManager.accelerometerUpdateInterval = self.updateInterval;
[self.motionManager startAccelerometerUpdatesToQueue:queue withHandler:^(CMAccelerometerData * _Nullable accelerometerData, NSError * _Nullable error) {
if (error) {
NSLog(@"%@",error.description);
}
else {
//在這里進(jìn)行屏幕方向的判斷
// NSLog(@"x = %lf, y = %lf, z = %lf",accelerometerData.acceleration.x, accelerometerData.acceleration.y, accelerometerData.acceleration.z);
CGFloat x = accelerometerData.acceleration.x;
CGFloat y = accelerometerData.acceleration.y;
CGFloat z = accelerometerData.acceleration.z;
if (fabs(x) <= fabs(y)) {
if (y >= 0) {
NSLog(@"UIDeviceOrientationPortraitUpsideDown");
}
else {
NSLog(@"UIDeviceOrientationPortrait");
}
}
else {
if (x >= 0) {
NSLog(@"UIDeviceOrientationLandscapeRight");
}
else {
NSLog(@"UIDeviceOrientationLandscapeLeft");
}
}
}
}];
}
else {
NSLog(@"The device does not support accelerometer!");
}
}
- (void)dealloc
{
self.motionManager = nil;
}
#pragma mark - Object Private Function
//上面的NSLog(@"x = %lf, y = %lf, z = %lf",accelerometerData.acceleration.x, accelerometerData.acceleration.y, accelerometerData.acceleration.z);一直不停止的回調(diào),因此可以在獲取想要的結(jié)果以后筋蓖,調(diào)用下面這個(gè)方法卸耘。
- (void)stopAcceleration
{
if ([self.motionManager isAccelerometerAvailable]) {
[self.motionManager stopAccelerometerUpdates];
}
}
@end
這里我采用的是push
的方式,系統(tǒng)會(huì)自動(dòng)的回調(diào)數(shù)據(jù)粘咖,我設(shè)置的采樣就是1s采樣15
次蚣抗,大約67ms
update一次數(shù)據(jù),我們看下面輸出瓮下。
2017-08-05 15:50:42.527385+0800 JJOC[7766:2999321] UIDeviceOrientationLandscapeLeft
2017-08-05 15:50:42.594454+0800 JJOC[7766:2999274] UIDeviceOrientationLandscapeLeft
2017-08-05 15:50:42.661608+0800 JJOC[7766:2999321] UIDeviceOrientationLandscapeLeft
2017-08-05 15:50:42.728912+0800 JJOC[7766:2999274] UIDeviceOrientationLandscapeLeft
2017-08-05 15:50:42.796129+0800 JJOC[7766:2999321] UIDeviceOrientationLandscapeLeft
2017-08-05 15:50:42.863421+0800 JJOC[7766:2999274] UIDeviceOrientationLandscapeLeft
2017-08-05 15:50:42.930696+0800 JJOC[7766:2999321] UIDeviceOrientationLandscapeLeft
2017-08-05 15:50:42.998406+0800 JJOC[7766:2999274] UIDeviceOrientationLandscapeLeft
2017-08-05 15:50:43.065164+0800 JJOC[7766:2999321] UIDeviceOrientationLandscapeLeft
2017-08-05 15:50:43.132831+0800 JJOC[7766:2999274] UIDeviceOrientationLandscapeLeft
2017-08-05 15:50:43.199666+0800 JJOC[7766:2999321] UIDeviceOrientationLandscapeLeft
2017-08-05 15:50:43.266782+0800 JJOC[7766:2999274] UIDeviceOrientationLandscapeLeft
2017-08-05 15:50:43.334437+0800 JJOC[7766:2999321] UIDeviceOrientationLandscapeLeft
2017-08-05 15:50:43.401540+0800 JJOC[7766:2999274] UIDeviceOrientationLandscapeLeft
2017-08-05 15:50:43.468730+0800 JJOC[7766:2999321] UIDeviceOrientationLandscapeLeft
2017-08-05 15:50:43.536152+0800 JJOC[7766:2999274] UIDeviceOrientationLandscapeLeft
2017-08-05 15:50:43.604181+0800 JJOC[7766:2999321] UIDeviceOrientationLandscapeLeft
2017-08-05 15:50:43.670330+0800 JJOC[7766:2999274] UIDeviceOrientationLandscapeLeft
2017-08-05 15:50:43.737794+0800 JJOC[7766:2999321] UIDeviceOrientationLandscapeLeft
2017-08-05 15:50:43.804924+0800 JJOC[7766:2999274] UIDeviceOrientationLandscapeLeft
2017-08-05 15:50:43.872237+0800 JJOC[7766:2999321] UIDeviceOrientationLandscapeLeft
確實(shí)是這樣的翰铡。
pull
接下來(lái)我們看一下pull
形式的代碼怎么去寫,pull
其實(shí)就是基于事件進(jìn)行驅(qū)動(dòng)的讽坏,有事件需要的才會(huì)觸發(fā)锭魔。
//pull
1. JJPullAcceleratorVC.m
#import "JJPullAcceleratorVC.h"
#import <CoreMotion/CoreMotion.h>
@interface JJPullAcceleratorVC ()
@property (nonatomic, strong) CMMotionManager *motionManager;
@property (nonatomic, assign) CMAcceleration acc;
@end
@implementation JJPullAcceleratorVC
#pragma mark - Override Base Function
- (void)viewDidLoad
{
[super viewDidLoad];
self.view.backgroundColor = [UIColor greenColor];
self.motionManager = [[CMMotionManager alloc] init];
}
- (void)dealloc
{
self.motionManager = nil;
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
//pull,基于事件進(jìn)行驅(qū)動(dòng),有事件才會(huì)去調(diào)用
if ([self.motionManager isAccelerometerAvailable]) {
//開始采用路呜,并獲得采樣數(shù)據(jù)
[self.motionManager startAccelerometerUpdates];
self.acc = self.motionManager.accelerometerData.acceleration;
[self startAccelerometer];
}
}
#pragma mark - Object Private Function
- (void)stopAcceleration
{
if ([self.motionManager isAccelerometerAvailable]) {
[self.motionManager stopAccelerometerUpdates];
}
}
- (void)startAccelerometer
{
CGFloat x = self.acc.x;
CGFloat y = self.acc.y;
CGFloat z = self.acc.z;
if (fabs(x) <= fabs(y)) {
if (y >= 0) {
NSLog(@"UIDeviceOrientationPortraitUpsideDown");
}
else {
NSLog(@"UIDeviceOrientationPortrait");
}
}
else {
if (x >= 0) {
NSLog(@"UIDeviceOrientationLandscapeRight");
}
else {
NSLog(@"UIDeviceOrientationLandscapeLeft");
}
}
}
@end
下面看一下輸出結(jié)果
2017-08-05 16:53:12.998816+0800 JJOC[7796:3011684] UIDeviceOrientationLandscapeRight
2017-08-05 16:53:13.201374+0800 JJOC[7796:3011684] UIDeviceOrientationLandscapeRight
2017-08-05 16:53:13.385063+0800 JJOC[7796:3011684] UIDeviceOrientationLandscapeRight
2017-08-05 16:53:13.568807+0800 JJOC[7796:3011684] UIDeviceOrientationLandscapeRight
2017-08-05 16:53:14.849985+0800 JJOC[7796:3011684] UIDeviceOrientationPortraitUpsideDown
2017-08-05 16:53:15.016851+0800 JJOC[7796:3011684] UIDeviceOrientationPortraitUpsideDown
2017-08-05 16:53:15.217770+0800 JJOC[7796:3011684] UIDeviceOrientationPortraitUpsideDown
2017-08-05 16:53:15.367570+0800 JJOC[7796:3011684] UIDeviceOrientationPortraitUpsideDown
2017-08-05 16:53:15.516851+0800 JJOC[7796:3011684] UIDeviceOrientationPortraitUpsideDown
我這里是點(diǎn)擊一下屏幕就采樣一次迷捧,不會(huì)像push
那樣,以固定的采樣率進(jìn)行采樣拣宰。
后記
未完党涕,待續(xù)~~~