CoreMotion框架(二)—— 利用加速度計(jì)獲取設(shè)備的方向

版本記錄

版本號(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次蚣抗,大約67msupdate一次數(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ù)~~~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市巡社,隨后出現(xiàn)的幾起案子膛堤,更是在濱河造成了極大的恐慌,老刑警劉巖晌该,帶你破解...
    沈念sama閱讀 222,104評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件肥荔,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡朝群,警方通過(guò)查閱死者的電腦和手機(jī)燕耿,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,816評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)姜胖,“玉大人誉帅,你說(shuō)我怎么就攤上這事∮依常” “怎么了蚜锨?”我有些...
    開封第一講書人閱讀 168,697評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)慢蜓。 經(jīng)常有香客問(wèn)我亚再,道長(zhǎng),這世上最難降的妖魔是什么晨抡? 我笑而不...
    開封第一講書人閱讀 59,836評(píng)論 1 298
  • 正文 為了忘掉前任氛悬,我火速辦了婚禮则剃,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘如捅。我一直安慰自己棍现,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,851評(píng)論 6 397
  • 文/花漫 我一把揭開白布伪朽。 她就那樣靜靜地躺著轴咱,像睡著了一般。 火紅的嫁衣襯著肌膚如雪烈涮。 梳的紋絲不亂的頭發(fā)上朴肺,一...
    開封第一講書人閱讀 52,441評(píng)論 1 310
  • 那天,我揣著相機(jī)與錄音坚洽,去河邊找鬼戈稿。 笑死,一個(gè)胖子當(dāng)著我的面吹牛讶舰,可吹牛的內(nèi)容都是我干的鞍盗。 我是一名探鬼主播,決...
    沈念sama閱讀 40,992評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了杰标?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,899評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤敷存,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后堪伍,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體锚烦,經(jīng)...
    沈念sama閱讀 46,457評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,529評(píng)論 3 341
  • 正文 我和宋清朗相戀三年帝雇,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了涮俄。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,664評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡尸闸,死狀恐怖彻亲,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情吮廉,我是刑警寧澤睹栖,帶...
    沈念sama閱讀 36,346評(píng)論 5 350
  • 正文 年R本政府宣布,位于F島的核電站茧痕,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏恼除。R本人自食惡果不足惜踪旷,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,025評(píng)論 3 334
  • 文/蒙蒙 一曼氛、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧令野,春花似錦舀患、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,511評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至现使,卻和暖如春低匙,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背碳锈。 一陣腳步聲響...
    開封第一講書人閱讀 33,611評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工顽冶, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人售碳。 一個(gè)月前我還...
    沈念sama閱讀 49,081評(píng)論 3 377
  • 正文 我出身青樓强重,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親贸人。 傳聞我的和親對(duì)象是個(gè)殘疾皇子间景,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,675評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容