iOS使用CoreMotion實現(xiàn)搖一搖功能
現(xiàn)在網(wǎng)上介紹的iOS搖一搖功能,基本是以借助系統(tǒng)的ShakeToEdit功能來實現(xiàn),什么是ShakeToEdit?看下圖應(yīng)該就能懂:
怎么實現(xiàn)?請看以下代碼:
//ViewController 加入以下兩方法 -(BOOL)canBecomeFirstResponder { //讓當(dāng)前controller可以成為firstResponder,這很重要 return YES; } -(void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event { if (event.subtype==UIEventSubtypeMotionShake) { //做你想做的事 } } //在viewDidView中調(diào)用以下消息,主動讓當(dāng)前controller成為firstResponder [self becomeFirstResponder]; //已經(jīng)不需要其它多余代碼了
這個方法最簡單,但這個功能有時候會失效。它失效的時候,系統(tǒng)所有搖一搖撤銷重做都會不起作用,從而導(dǎo)致包括所有關(guān)聯(lián)的Shake事件也不起作用。失效原因或在什么情況下失效,目前還沒有相關(guān)資料。據(jù)這兩天個人觀察,大多發(fā)生在手機放在褲袋中走10多分鐘路之后(iPhone5S iOS 7.05).是否因為搖得太久了,系統(tǒng)為了省電就關(guān)閉此功能呢?希望大家也拿自己手機來試一試,我們一起來看看這到底是什么問題。
要恢復(fù),最直接的是連接iTunes,否則,就要讓手機平放一段時間,但時候平放一天都沒有恢復(fù)。所以說此方式不太穩(wěn)定,微信及其它有搖一搖功能的應(yīng)用,他們的搖一搖并不受此影響,而且微信的搖一搖動作比ShakeToEdit要輕,可以講手動動一下就激活了。于是我認(rèn)為,這些應(yīng)用都放棄了ShakeToEdit,使用了加速儀,自己重新實現(xiàn)。
使用加速儀與使用相機,聲音之類不同,不需要經(jīng)過用戶允許,也沒有訪問限制,當(dāng)然也沒什么危害,是個基本配備。那要怎么做?下面費話不多說,直接開始吧:
第一步,為項目TARGET添加CoreMotion.framework
第二步,引入頭文件
#import <CoreMotion/CoreMotion.h>
第三步,使用CMMotionManager
@property (strong,nonatomic) CMMotionManager *motionManager;
注意,當(dāng)前應(yīng)用只能有一個CMMotionManager實例,多個實例會影響接收速率
第四步,實例并初始化加速儀
self.motionManager = [[CMMotionManager alloc] init];//一般在viewDidLoad中進(jìn)行 self.motionManager.accelerometerUpdateInterval = .1;//加速儀更新頻率,以秒為單位
第五步,開始接收加速儀數(shù)據(jù)(startAccelerometerUpdatesToQueue:withHandler:)
-(void)viewDidAppear:(BOOL)animated { [self startAccelerometer]; } -(void)startAccelerometer { //以push的方式更新并在block中接收加速度 [self.motionManager startAccelerometerUpdatesToQueue:[[NSOperationQueue alloc]init] withHandler:^(CMAccelerometerData *accelerometerData, NSError *error) { [self outputAccelertionData:accelerometerData.acceleration]; if (error) { NSLog(@"motion error:%@",error); } }]; } -(void)outputAccelertionData:(CMAcceleration)acceleration { //綜合3個方向的加速度 double accelerameter =sqrt( pow( acceleration.x , 2 ) + pow( acceleration.y , 2 ) + pow( acceleration.z , 2) ); //當(dāng)綜合加速度大于2.3時,就激活效果(此數(shù)值根據(jù)需求可以調(diào)整,數(shù)據(jù)越小,用戶搖動的動作就越小,越容易激活,反之加大難度,但不容易誤觸發(fā)) if (accelerameter>2.3f) { //立即停止更新加速儀(很重要?。? [self.motionManager stopAccelerometerUpdates]; dispatch_async(dispatch_get_main_queue(), ^{ //UI線程必須在此block內(nèi)執(zhí)行,例如搖一搖動畫、UIAlertView之類 }); } } -(void)viewDidDisappear:(BOOL)animated { //停止加速儀更新(很重要!) [self.motionManager stopAccelerometerUpdates]; }
最后一步
至此,搖一搖核心已經(jīng)實現(xiàn),但還差最后一步:當(dāng)App退到后臺時必須停止加速儀更新,回到當(dāng)前時重新執(zhí)行。否則應(yīng)用在退到后臺依然會接收加速度更新,可能會與其它當(dāng)前應(yīng)用沖突,產(chǎn)生不好的體驗。所以,分別在viewDidAppear和viewDidDisappear中加入如下監(jiān)聽:
//viewDidAppear中加入 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(receiveNotification:) name:UIApplicationDidEnterBackgroundNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(receiveNotification:) name:UIApplicationWillEnterForegroundNotification object:nil];
//viewDidDisappear中取消監(jiān)聽 [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidEnterBackgroundNotification object:nil]; [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationWillEnterForegroundNotification object:nil];
//對應(yīng)上面的通知中心回調(diào)的消息接收 -(void)receiveNotification:(NSNotification *)notification { if ([notification.name isEqualToString:UIApplicationDidEnterBackgroundNotification]) { [self.motionManager stopAccelerometerUpdates]; }else{ [self startAccelerometer]; }}
至此,所有使用加速儀實現(xiàn)搖一搖功能的實現(xiàn)方式已介紹完畢。
一些可改進(jìn)的地方:
1) 搖一搖動作捕捉——如果僅是以加速度大小來判定,有可能用戶突然快速移動手機時就激活了搖動,但用戶比較稍稍慢一些來回晃動手機卻不會激活,可能與用戶期望的稍微有出入。系統(tǒng)的ShakeToEdit就能做得比較到位。
我們可以結(jié)合定時器與加速度的正反方向來更精確判定用戶的搖一搖動作,例如:綜合加速度改為帶方向的向量,然后當(dāng)1.5秒內(nèi)有相反兩個方向大于某個數(shù)值的加速度,才算為一個搖動行為。這個1.5秒時間需要通過實際測試來取值,當(dāng)某次取得的加速度值大于某個值開始統(tǒng)計下一個加速度向量,此值也需要實測來取值,可能1.5左右就夠了。
2) App狀態(tài)更改——如果激活的搖一搖是個長時間等待行為,例如彈出ActionSheet讓用戶選擇操作。在用戶進(jìn)行下一步操作前,ActionSheet沒消失前,不應(yīng)該啟動下一次監(jiān)聽,包括應(yīng)用從后臺回到當(dāng)前狀態(tài)后,也要判斷用戶是否有過下一步行為。
參考文獻(xiàn):鏈接地址
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
iOS面試中如何優(yōu)雅回答B(yǎng)lock導(dǎo)致循環(huán)引用的問題
這篇文章主要給大家介紹了iOS面試中關(guān)于如何優(yōu)雅回答B(yǎng)lock導(dǎo)致循環(huán)引用的問題的相關(guān)資料,文中通過圖文介紹的非常相信,相信對大家具有一定的參考價值,需要的朋友們下面來一起看看吧。2017-03-03IOS 開發(fā)之對象為空的判斷(nil、null)詳解
這篇文章主要介紹了IOS 開發(fā)之對象為空的判斷(nil、null)詳解的相關(guān)資料,需要的朋友可以參考下2017-02-02IOS UI學(xué)習(xí)教程之使用UIImageView控件制作動畫
這篇文章主要為大家詳細(xì)介紹了IOS UI學(xué)習(xí)教程之使用UIImageView控件制作動畫,感興趣的小伙伴們可以參考一下2016-03-03iOS 本地視頻和網(wǎng)絡(luò)視頻流播放實例代碼
本篇文章主要介紹了iOS 本地視頻和網(wǎng)絡(luò)視頻流播放實例代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-07-07iOS實現(xiàn)相冊和網(wǎng)絡(luò)圖片的存取
本篇文章主要介紹了iOS實現(xiàn)相冊和網(wǎng)絡(luò)圖片的存取,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-04-04