当有人摇晃iPhone时,我想做出反应。我并不特别在意他们是如何摇晃它的,只在意它在一瞬间被使劲地挥舞着。有人知道怎么检测吗?
当前回答
你需要通过accelerometer:didAccelerate: method检查加速度计,这是UIAccelerometerDelegate协议的一部分,检查这些值是否超过了震动所需的移动量的阈值。
在AppController底部的accelerometer:didAccelerate:方法中有一些不错的示例代码。m在GLPaint例子中,这个例子可以在iPhone开发者网站上找到。
其他回答
这是你需要的基本委托代码:
#define kAccelerationThreshold 2.2
#pragma mark -
#pragma mark UIAccelerometerDelegate Methods
- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration
{
if (fabsf(acceleration.x) > kAccelerationThreshold || fabsf(acceleration.y) > kAccelerationThreshold || fabsf(acceleration.z) > kAccelerationThreshold)
[self myShakeMethodGoesHere];
}
也在接口中的适当代码中设置。即:
@interface MyViewController: UIViewController <UIPickerViewDelegate, UIPickerViewDataSource, UIAccelerometerDelegate>
首先,肯德尔7月10日的回答是正确的。
现在…我想做一些类似的事情(在iPhone OS 3.0+),只是在我的情况下,我想在整个应用程序范围内,这样我就可以在震动发生时提醒应用程序的各个部分。这是我最后做的事情。
首先,我子类化了UIWindow。这很容易。创建一个带有接口的类文件,如MotionWindow: UIWindow(随意选择你自己的)。添加一个这样的方法:
- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event {
if (event.type == UIEventTypeMotion && event.subtype == UIEventSubtypeMotionShake) {
[[NSNotificationCenter defaultCenter] postNotificationName:@"DeviceShaken" object:self];
}
}
更改@"DeviceShaken"为您选择的通知名称。保存文件。
现在,如果你使用主窗口。xib (Xcode模板中常用的东西)然后把Window对象的类从UIWindow改成MotionWindow或者其他什么。保存xib。如果你以编程的方式设置UIWindow,请使用你的新Window类。
现在你的应用正在使用专门的UIWindow类。无论你想在哪里被告知摇晃,注册他们的通知!是这样的:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(deviceShaken) name:@"DeviceShaken" object:nil];
把自己从观察者的身份移开:
[[NSNotificationCenter defaultCenter] removeObserver:self];
我把我的放在viewWillAppear:和viewWillDisappear:视图控制器相关的地方。确保您对震动事件的响应知道它是否“已经在进行中”。否则,如果设备连续摇晃两次,你就会遇到小塞车。通过这种方式,您可以忽略其他通知,直到真正完成对原始通知的响应。
你也可以选择motionBegan和motionEnded的cue off。由你决定。在我的例子中,效果总是需要在设备休息后发生(而不是当它开始摇晃时),所以我使用motionEnded。两个都试一下,看看哪个更有意义……或者检测/通知两者!
这里还有一个(奇怪的?)观察:注意,这段代码中没有第一响应器管理的迹象。到目前为止,我只尝试了表视图控制器,一切似乎都很好地工作在一起!但我不能保证其他情况。
Kendall等人——有人能解释一下为什么UIWindow子类会这样吗?是因为窗户位于食物链的顶端吗?
在3.0,现在有一个更简单的方法-挂钩到新的运动事件。
主要的技巧是你需要有一些UIView(不是UIViewController)你想要作为firstResponder来接收震动事件消息。这是你可以在任何UIView中使用的代码来获取震动事件:
@implementation ShakingView
- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event
{
if ( event.subtype == UIEventSubtypeMotionShake )
{
// Put in code here to handle shake
}
if ( [super respondsToSelector:@selector(motionEnded:withEvent:)] )
[super motionEnded:motion withEvent:event];
}
- (BOOL)canBecomeFirstResponder
{ return YES; }
@end
你可以很容易地将任何UIView(甚至是系统视图)转换为一个视图,只需用这些方法子类化视图(然后选择这个新类型而不是IB中的基类型,或者在分配视图时使用它)就可以获得抖动事件。
在视图控制器中,你想要将这个视图设置为第一响应器:
- (void) viewWillAppear:(BOOL)animated
{
[shakeView becomeFirstResponder];
[super viewWillAppear:animated];
}
- (void) viewWillDisappear:(BOOL)animated
{
[shakeView resignFirstResponder];
[super viewWillDisappear:animated];
}
不要忘记,如果你有其他视图成为用户操作的第一响应器(如搜索栏或文本输入字段),当其他视图退出时,你还需要恢复震动视图的第一响应器状态!
即使您将applicationSupportsShakeToEdit设置为NO,此方法也有效。
在iOS 8.3(也许更早)的Swift中,重写视图控制器中的motionBegan或motionEnded方法非常简单:
class ViewController: UIViewController {
override func motionBegan(motion: UIEventSubtype, withEvent event: UIEvent) {
println("started shaking!")
}
override func motionEnded(motion: UIEventSubtype, withEvent event: UIEvent) {
println("ended shaking!")
}
}
为了在整个应用范围内启用这个功能,我在UIWindow上创建了一个类别:
@implementation UIWindow (Utils)
- (BOOL)canBecomeFirstResponder
{
return YES;
}
- (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event
{
if (motion == UIEventSubtypeMotionShake) {
// Do whatever you want here...
}
}
@end
推荐文章
- 如何使用iOS创建GUID/UUID
- 禁用所呈现视图控制器的交互式撤销
- 点击按钮时如何打开手机设置?
- 如何使用UIVisualEffectView来模糊图像?
- 如何修复UITableView分隔符在iOS 7?
- 故事板中的自定义单元格行高设置没有响应
- 在Swift中使用自定义消息抛出错误/异常的最简单方法?
- 如何在Swift中获得唯一的设备ID ?
- 复制文本到剪贴板与iOS
- 在Swift中根据字符串计算UILabel的大小
- 如何调用手势点击在UIView编程在迅速
- 我如何隐藏在一个Swift iOS应用程序的状态栏?
- 在iPad上使用iOS 8正确呈现UIAlertController
- 尝试将一个非属性列表对象设置为NSUserDefaults
- 如何改变导航栏的颜色在iOS 7?