ios 摇一摇实现

原文地址:iOS使用CoreMotion实现摇一摇功能

现在网上介绍的iOS摇一摇功能,基本是以借助系统的ShakeToEdit功能来实现,什么是ShakeToEdit?看下图应该就能懂:

怎么实现?请看以下代码:

[objc]view plaincopy

//ViewController 加入以下两方法

-(BOOL)canBecomeFirstResponder

{

//让当前controller可以成为firstResponder,这很重要

returnYES;

}

-(void)motionEnded:(UIEventSubtype)motionwithEvent:(UIEvent*)event

{

if(event.subtype==UIEventSubtypeMotionShake) {

//做你想做的事

}

}

//在viewDidView中调用以下消息,主动让当前controller成为firstResponder

[selfbecomeFirstResponder];

//已经不需要其它多余代码了

这个方法最简单,但这个功能有时候会失效。它失效的时候,系统所有摇一摇撤销重做都会不起作用,从而导致包括所有关联的Shake事件也不起作用。失效原因或在什么情况下失效,目前还没有相关资料。据这两天个人观察,大多发生在手机放在裤袋中走10多分钟路之后(iPhone5S iOS 7.05).是否因为摇得太久了,系统为了省电就关闭此功能呢?希望大家也拿自己手机来试一试,我们一起来看看这到底是什么问题。

要恢复,最直接的是连接iTunes,否则,就要让手机平放一段时间,但时候平放一天都没有恢复。所以说此方式不太稳定,微信及其它有摇一摇功能的应用,他们的摇一摇并不受此影响,而且微信的摇一摇动作比ShakeToEdit要轻,可以讲手动动一下就激活了。于是我认为,这些应用都放弃了ShakeToEdit,使用了加速仪,自己重新实现。

使用加速仪与使用相机,声音之类不同,不需要经过用户允许,也没有访问限制,当然也没什么危害,是个基本配备。那要怎么做?下面费话不多说,直接开始吧:

第一步,为项目TARGET添加CoreMotion.framework

第二步,引入头文件

[objc]view plaincopy

#import 

第三步,使用CMMotionManager

[objc]view plaincopy

@property(strong,nonatomic)CMMotionManager*motionManager;

注意,当前应用只能有一个CMMotionManager实例,多个实例会影响接收速率

第四步,实例并初始化加速仪

[objc]view plaincopy

self.motionManager= [[CMMotionManageralloc]init];//一般在viewDidLoad中进行

self.motionManager.accelerometerUpdateInterval=.1;//加速仪更新频率,以秒为单位

第五步,开始接收加速仪数据(startAccelerometerUpdatesToQueue:withHandler:

[objc]view plaincopy

-(void)viewDidAppear:(BOOL)animated

{

[selfstartAccelerometer];

}

-(void)startAccelerometer

{

//以push的方式更新并在block中接收加速度

[self.motionManagerstartAccelerometerUpdatesToQueue:[[NSOperationQueuealloc]init]

withHandler:^(CMAccelerometerData*accelerometerData,NSError*error) {

[selfoutputAccelertionData:accelerometerData.acceleration];

if(error) {

NSLog(@"motion error:%@",error);

}

}];

}

-(void)outputAccelertionData:(CMAcceleration)acceleration

{

//综合3个方向的加速度

doubleaccelerameter =sqrt( pow( acceleration.x,2) + pow( acceleration.y,2)

+ pow( acceleration.z,2) );

//当综合加速度大于2.3时,就激活效果(此数值根据需求可以调整,数据越小,用户摇动的动作就越小,越容易激活,反之加大难度,但不容易误触发)

if(accelerameter>2.3f) {

//立即停止更新加速仪(很重要!)

[self.motionManagerstopAccelerometerUpdates];

dispatch_async(dispatch_get_main_queue(), ^{

//UI线程必须在此block内执行,例如摇一摇动画、UIAlertView之类

});

}

}

-(void)viewDidDisappear:(BOOL)animated

{

//停止加速仪更新(很重要!)

[self.motionManagerstopAccelerometerUpdates];

}

最后一步

至此,摇一摇核心已经实现,但还差最后一步:当App退到后台时必须停止加速仪更新,回到当前时重新执行。否则应用在退到后台依然会接收加速度更新,可能会与其它当前应用冲突,产生不好的体验。所以,分别在viewDidAppear和viewDidDisappear中加入如下监听:

[objc]view plaincopy

//viewDidAppear中加入

[[NSNotificationCenterdefaultCenter]addObserver:self

selector:@selector(receiveNotification:)

name:UIApplicationDidEnterBackgroundNotificationobject:nil];

[[NSNotificationCenterdefaultCenter]addObserver:self

selector:@selector(receiveNotification:)

name:UIApplicationWillEnterForegroundNotificationobject:nil];

[objc]view plaincopy

//viewDidDisappear中取消监听

[[NSNotificationCenterdefaultCenter]removeObserver:self

name:UIApplicationDidEnterBackgroundNotificationobject:nil];

[[NSNotificationCenterdefaultCenter]removeObserver:self

name:UIApplicationWillEnterForegroundNotificationobject:nil];

[objc]view plaincopy

//对应上面的通知中心回调的消息接收

-(void)receiveNotification:(NSNotification*)notification

{

if([notification.name

isEqualToString:UIApplicationDidEnterBackgroundNotification])

{

[self.motionManagerstopAccelerometerUpdates];

}else{

[selfstartAccelerometer];

}}

至此,所有使用加速仪实现摇一摇功能的实现方式已介绍完毕。

一些可改进的地方:

1) 摇一摇动作捕捉——如果仅是以加速度大小来判定,有可能用户突然快速移动手机时就激活了摇动,但用户比较稍稍慢一些来回晃动手机却不会激活,可能与用户期望的稍微有出入。系统的ShakeToEdit就能做得比较到位。

我们可以结合定时器与加速度的正反方向来更精确判定用户的摇一摇动作,例如:综合加速度改为带方向的向量,然后当1.5秒内有相反两个方向大于某个数值的加速度,才算为一个摇动行为。这个1.5秒时间需要通过实际测试来取值,当某次取得的加速度值大于某个值开始统计下一个加速度向量,此值也需要实测来取值,可能1.5左右就够了。

2) App状态更改——如果激活的摇一摇是个长时间等待行为,例如弹出ActionSheet让用户选择操作。在用户进行下一步操作前,ActionSheet没消失前,不应该启动下一次监听,包括应用从后台回到当前状态后,也要判断用户是否有过下一步行为。

参考文献:

https://developer.apple.com/library/ios/documentation/EventHandling/Conceptual/EventHandlingiPhoneOS/motion_event_basics/motion_event_basics.html#//apple_ref/doc/uid/TP40009541-CH6-SW1

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,482评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,377评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,762评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,273评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,289评论 5 373
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,046评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,351评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,988评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,476评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,948评论 2 324
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,064评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,712评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,261评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,264评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,486评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,511评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,802评论 2 345

推荐阅读更多精彩内容