iOS使用CoreMotion实现摇一摇功能

所属分类: 软件编程 / IOS 阅读数: 368
收藏 0 赞 0 分享

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

 

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

//ViewController 加入以下两方法 
-(BOOL)canBecomeFirstResponder 
{ 
//让当前controller可以成为firstResponder,这很重要 
  return YES; 
} 
-(void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event 
{ 
  if (event.subtype==UIEventSubtypeMotionShake) { 
    //做你想做的事 
  } 
} 
//在viewDidView中调用以下消息,主动让当前controller成为firstResponder 
[self becomeFirstResponder]; 
//已经不需要其它多余代码了 

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

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

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

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

 

第二步,引入头文件

#import <CoreMotion/CoreMotion.h> 

第三步,使用CMMotionManager

@property (strong,nonatomic) CMMotionManager *motionManager; 

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

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

self.motionManager = [[CMMotionManager alloc] init];//一般在viewDidLoad中进行 
self.motionManager.accelerometerUpdateInterval = .1;//加速仪更新频率,以秒为单位 

第五步,开始接收加速仪数据(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) ); 
  //当综合加速度大于2.3时,就激活效果(此数值根据需求可以调整,数据越小,用户摇动的动作就越小,越容易激活,反之加大难度,但不容易误触发) 
  if (accelerameter>2.3f) { 
 //立即停止更新加速仪(很重要!) 
    [self.motionManager stopAccelerometerUpdates]; 
     
    dispatch_async(dispatch_get_main_queue(), ^{ 
      //UI线程必须在此block内执行,例如摇一摇动画、UIAlertView之类 
    }); 
  }   
} 
-(void)viewDidDisappear:(BOOL)animated 
{ 
  //停止加速仪更新(很重要!) 
  [self.motionManager stopAccelerometerUpdates]; 
} 

最后一步

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

//viewDidAppear中加入 
[[NSNotificationCenter defaultCenter] addObserver:self 
     selector:@selector(receiveNotification:) 
     name:UIApplicationDidEnterBackgroundNotification object:nil]; 
[[NSNotificationCenter defaultCenter] addObserver:self 
     selector:@selector(receiveNotification:) 
     name:UIApplicationWillEnterForegroundNotification object:nil]; 
//viewDidDisappear中取消监听 
[[NSNotificationCenter defaultCenter] removeObserver:self 
     name:UIApplicationDidEnterBackgroundNotification object:nil]; 
[[NSNotificationCenter defaultCenter] removeObserver:self 
     name:UIApplicationWillEnterForegroundNotification object:nil]; 
//对应上面的通知中心回调的消息接收 
-(void)receiveNotification:(NSNotification *)notification 
{ 
  if ([notification.name  
    isEqualToString:UIApplicationDidEnterBackgroundNotification]) 
  { 
    [self.motionManager stopAccelerometerUpdates]; 
  }else{ 
    [self startAccelerometer]; 
 }} 

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

一些可改进的地方:

  1) 摇一摇动作捕捉——如果仅是以加速度大小来判定,有可能用户突然快速移动手机时就激活了摇动,但用户比较稍稍慢一些来回晃动手机却不会激活,可能与用户期望的稍微有出入。系统的ShakeToEdit就能做得比较到位。
   我们可以结合定时器与加速度的正反方向来更精确判定用户的摇一摇动作,例如:综合加速度改为带方向的向量,然后当1.5秒内有相反两个方向大于某个数值的加速度,才算为一个摇动行为。这个1.5秒时间需要通过实际测试来取值,当某次取得的加速度值大于某个值开始统计下一个加速度向量,此值也需要实测来取值,可能1.5左右就够了。

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

参考文献:链接地址

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

更多精彩内容其他人还在看

iOS 仿百度外卖-首页重力感应的实例

这篇文章主要介绍了iOS 仿百度外卖-首页重力感应的实例,具有一定的参考价值,感兴趣的小伙伴们可以参考一下。
收藏 0 赞 0 分享

iOS实现时间显示几分钟前,几小时前以及刚刚的方法示例

这篇文章主要介绍了如何利用iOS实现时间显示是在几小时前,几分钟前以及刚刚的格式,类似大家在qq空间和朋友圈微博看到的效果,文中给出了详细的示例代码,有需要的朋友们可以参考借鉴,下面来一起学习学习吧。
收藏 0 赞 0 分享

iOS 条码及二维码扫描(从相册中读取条形码/二维码)及扫码过程中遇到的坑

本文主要给大家介绍ios中从手机相册中读取条形码和二维码的问题及解决办法,需要的朋友参考下
收藏 0 赞 0 分享

IOS Cache设计详细介绍及简单示例

这篇文章主要介绍了IOS Cache设计详细介绍及简单示例的相关资料,Cache的目的是为了追求更高的速度体验,Cache的源头是两种数据读取方式在成本和性能上的差异,需要的朋友可以参考下
收藏 0 赞 0 分享

iOS本地动态生成验证码的方法

这篇文章主要介绍了iOS本地动态生成验证码的方法,非常不错,具有参考借鉴价值,需要的朋友可以参考下
收藏 0 赞 0 分享

iOS绘制3D饼图的实现方法

饼图常用于统计学模块。常见的一般为2D饼图,这篇文章主要介绍了iOS绘制3D饼图的实现方法,3D饼图更加立体,用户的好感度也比较高,下面需要的朋友可以参考借鉴,一起来看看吧。
收藏 0 赞 0 分享

谈谈iOS开发之JSON格式数据的生成与解析

JSON格式取代了xml给网络传输带来了很大的便利,本篇文章主要介绍了iOS开发:对象直接转化成JSON详解,具有一定的参考价值,有兴趣的可以了解一下。
收藏 0 赞 0 分享

IOS 身份证校验详细介绍及示例代码

这篇文章主要介绍了IOS 身份证校验详细介绍及示例代码的相关资料,这里对身份校验比较详细,附有简单实例,需要的朋友可以参考下
收藏 0 赞 0 分享

IOS 自定义UICollectionView的头视图或者尾视图UICollectionReusableView

这篇文章主要介绍了IOS 自定义UICollectionView的头视图或者尾视图UICollectionReusableView的相关资料,需要的朋友可以参考下
收藏 0 赞 0 分享

IOS 仿支付宝支付屏幕亮度变化机制

这篇文章主要介绍了IOS 仿支付宝支付屏幕亮度变化机制的相关资料,非常不错,具有参考借鉴价值,需要的朋友可以参考下
收藏 0 赞 0 分享
查看更多