让当前的程序 检测手机晃动的方法大体上有两种:
第一种方法就是重写UIResponder类下的手势方法(可以用模拟器模拟);
第二种方法就是利用Accelerometer来检测手机是否晃动(只能用真机测试)。
第一种方法:
很简单只需三个步骤:让当前ViewController支持晃动手势,让当前的View成为第一响应者,重写UIResponder中支持晃动的3个方法。
1、让当前的ViewController支持晃动;
1 - (void)viewDidLoad 2 { 3 [super viewDidLoad]; 4 // 支持shake 5 [[UIApplication sharedApplication] setApplicationSupportsShakeToEdit:YES]; 6 }
2、让当前的View成为第一响应者;
1 -(BOOL)canBecomeFirstResponder 2 { 3 // 默认值是 NO 4 return YES; 5 } 6 7 -(void)viewDidAppear:(BOOL)animated 8 { 9 [superviewDidAppear:animated]; 10 [self becomeFirstResponder]; 11 } 12 13 -(void)viewWillDisappear:(BOOL)animated 14 { 15 [self resignFirstResponder]; 16 [self viewWillDisappear:animated]; 17 }
3、重写下面的方法,并在相应的方法中添加手机晃动时需要执行的代码。
1 - (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event//开始晃动 2 3 - (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event//晃动结束 4 5 - (void)motionCancelled:(UIEventSubtype)motion withEvent:(UIEvent *)event//取消晃动
第二种方法:
其实根据acceleration判断手机是否晃动,细分又可分为两种,也可认为是一种。
闲话少说直接上代码:
1>使用UIAccelerometer对象检测手机是否晃动(iOS5.0及以后不推荐使用但仍然可以用,只是会有警告提示)
1 // 创建 UIAccelerometer实例 2 UIAccelerometer *accelerometer = [UIAccelerometersharedAccelerometer]; 3 accelerometer.updateInterval =0.1; 4 accelerometer.delegate =self; 5 // 实现UIAccelerometer实例的代理方法 6 -(void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration 7 { // iOS5.0 以后不推荐使用 8 if (fabs(acceleration.x)>2.0 ||fabs(acceleration.y)>2.0 ||fabs(acceleration.z)>2.0) { 9 NSLog(@"检测到晃动"); 10 } 11 }
2>使用CoreMotion框架,根据acceleration值来判断手机是否晃动。(CoreMotion框架是苹果推荐开发者使用的,用来替代UIAccelerometer;最后我会再粘贴一个介绍CoreMotion框架的链接,感觉讲的不错)
使用CMMotionManager来获取accelerometer、gyro、deviceMotion等的信息,有push和pull两种方式,关于这两种方式的优缺点可以在网上查找。
1、push方式获取acceleration数据,以下代码可以放到-(void)viewDidLoad方法中。
1 CMMotionManager *cmManager = [[CMMotionManageralloc]init]; 2 if (!cmManager.accelerometerAvailable) { 3 NSLog(@"CMMotionManager unavailable"); 4 } 5 cmManager.accelerometerUpdateInterval =0.1; // 数据更新时间间隔 6 [cmManager startAccelerometerUpdatesToQueue:[NSOperationQueuecurrentQueue]withHandler:^(CMAccelerometerData *accelerometerData,NSError *error) { 7 double x = accelerometerData.acceleration.x; 8 double y = accelerometerData.acceleration.y; 9 double z = accelerometerData.acceleration.z; 10 11 if (fabs(x)>2.0 ||fabs(y)>2.0 ||fabs(z)>2.0) { 12 NSLog(@"检测到晃动"); 13 } 14 NSLog(@"CoreMotionManager, x: %f,y: %f, z: %f",x,y,z); 15 }];
2、pull方式获取acceletation数据,需要自己实现计时器功能。以下代码可以放到-(void)viewDidLoad方法中。
1 CMMotionManager *cmManager = [[CMMotionManageralloc]init]; 2 if (!cmManager.accelerometerAvailable) { 3 NSLog(@"CMMotionManager unavailable"); 4 } 5 cmManager.accelerometerUpdateInterval =0.1f; 6 [cmManager startAccelerometerUpdates]; 7 timer = [NSTimerscheduledTimerWithTimeInterval:0.2ftarget:selfselector:@selector(updateAcceleration:)userInfo:nilrepeats:YES]; 8 [timerfire];
自定义方法updateAcceleration:
1 -(void)updateAcceleration:(id)userInfo 2 { 3 CMAccelerometerData *accelData =cmManager.accelerometerData; 4 double x = accelData.acceleration.x; 5 double y = accelData.acceleration.y; 6 double z = accelData.acceleration.z; 7 8 if (fabs(x)>2.0 ||fabs(y)>2.0 ||fabs(z)>2.0) { 9 NSLog(@"检测到晃动"); 10 } 11 }
不管push还是pull方法在最后一定要记得调用CoreMotion实例的 stopAccelerometerUpdates方法([cmManagerstopAccelerometerUpdates]),停止CoreMotion实例更新。