本节书摘来自异步社区《iOS 6高级开发手册(第4版)》一书中的第1章,第1.12节使用运动事件检测晃动,作者 【美】Erica Sadun,更多章节内容可以访问云栖社区“异步社区”公众号查看
1.12 使用运动事件检测晃动
iOS 6高级开发手册(第4版)
当iPhone检测到一个运动事件时,它会把该事件传递给当前的第一个响应者,即响应者链中的主对象。响应者是可以处理事件的对象,所有的视图和窗口都是响应者,因此也是应用程序对象。
响应者链提供了一种对象层次结构,所有的对象都可以响应事件。当朝向链开始处的对象接收到一个事件时,不会进一步传递那个事件。对象会处理它。如果它不能处理,可以把该事件转移给下一个响应者。
对象通常可以通过把它们自己声明为第一个响应者来获得这种身份,这是通过become FirstResponder实现的。在这个代码段中,UIViewController确保它会变成第一个响应者,只要它的视图出现在屏幕上即可。一旦消失,它将放弃第一个响应者的身份:
- (BOOL)canBecomeFirstResponder {
return YES;
}
// Become first responder whenever the view appears
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[self becomeFirstResponder];
}
// Resign first responder whenever the view disappears
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[self resignFirstResponder];
}
第一个响应者将接收所有的触摸和运动事件。运动回调反映了UIView触摸回调阶段。回调方法如下。
motionBegan:withEvent::这个回调指示运动事件的开始。在编写本书时,只能识别一类运动事件:晃动。将来可能不是这样,因此你可能想在代码中检查运动类型。
motionEnded:withEvent::在第一个响应者在运动事件结束时接收这个回调。
motionCancelled:withEvent::与触摸一样,可以通过打入的电话和其他系统事件取消运动。Apple建议在代码中实现全部3个运动事件回调(类似地,还要实现全部4个触摸事件回调)。
下面的代码段显示了一对运动回调的示例。如果在设备上测试它们,可以注意到几件事。第一,从用户的角度看,开始和结束事件几乎是同时发生的,为这两类事件播放声音有些小题大做。第二,它偏向于进行从一侧到另一侧的晃动检测,与前后和上下晃动相比,iPhone更擅长检测从一侧到另一侧的晃动。最后,Apple的运动实现使用了一种轻微锁定的方法。直到生成了另一个运动事件或者在处理了前一个运动事件之后,才能生成一个新的运动事件。Shake to Shuffle和Shake to Undo事件使用了相同的锁定机制:
- (void)motionBegan:(UIEventSubtype)motion
withEvent:(UIEvent *)event {
// Play a sound whenever a shake motion starts
if (motion != UIEventSubtypeMotionShake) return;
[self playSound:startSound];
}
- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event
{
// Play a sound whenever a shake motion ends
if (motion != UIEventSubtypeMotionShake) return;
[self playSound:endSound];
}