当有人摇晃iPhone时,我想做出反应。我并不特别在意他们是如何摇晃它的,只在意它在一瞬间被使劲地挥舞着。有人知道怎么检测吗?
当前回答
I came across this post looking for a "shaking" implementation. millenomi's answer worked well for me, although i was looking for something that required a bit more "shaking action" to trigger. I've replaced to Boolean value with an int shakeCount. I also reimplemented the L0AccelerationIsShaking() method in Objective-C. You can tweak the ammount of shaking required by tweaking the ammount added to shakeCount. I'm not sure i've found the optimal values yet, but it seems to be working well so far. Hope this helps someone:
- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration {
if (self.lastAcceleration) {
if ([self AccelerationIsShakingLast:self.lastAcceleration current:acceleration threshold:0.7] && shakeCount >= 9) {
//Shaking here, DO stuff.
shakeCount = 0;
} else if ([self AccelerationIsShakingLast:self.lastAcceleration current:acceleration threshold:0.7]) {
shakeCount = shakeCount + 5;
}else if (![self AccelerationIsShakingLast:self.lastAcceleration current:acceleration threshold:0.2]) {
if (shakeCount > 0) {
shakeCount--;
}
}
}
self.lastAcceleration = acceleration;
}
- (BOOL) AccelerationIsShakingLast:(UIAcceleration *)last current:(UIAcceleration *)current threshold:(double)threshold {
double
deltaX = fabs(last.x - current.x),
deltaY = fabs(last.y - current.y),
deltaZ = fabs(last.z - current.z);
return
(deltaX > threshold && deltaY > threshold) ||
(deltaX > threshold && deltaZ > threshold) ||
(deltaY > threshold && deltaZ > threshold);
}
PS: 我将更新间隔设置为1/15秒。
[[UIAccelerometer sharedAccelerometer] setUpdateInterval:(1.0 / 15)];
其他回答
最简单的解决方案是为你的应用程序派生一个新的根窗口:
@implementation OMGWindow : UIWindow
- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event {
if (event.type == UIEventTypeMotion && motion == UIEventSubtypeMotionShake) {
// via notification or something
}
}
@end
然后在你的应用委托中:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[OMGWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
//…
}
如果你使用的是故事板,这可能会更棘手,我不知道你在应用委托中需要精确的代码。
首先,肯德尔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子类会这样吗?是因为窗户位于食物链的顶端吗?
查看GLPaint示例。
http://developer.apple.com/library/ios/#samplecode/GLPaint/Introduction/Intro.html
抱歉把这篇文章作为一个答案而不是评论,但正如你所看到的,我是Stack Overflow的新手,所以我还没有足够的声誉来发表评论!
不管怎样,我第二个@cire关于确保设置第一响应器状态一旦视图是视图层次结构的一部分。例如,在视图控制器viewDidLoad方法中设置第一响应器状态是行不通的。如果你不确定它是否工作,[view becomeFirstResponder]返回一个你可以测试的布尔值。
另一点:如果你不想创建一个不必要的UIView子类,你可以使用一个视图控制器来捕获抖动事件。我知道没有那么麻烦,但还是有选择的。只是移动Kendall放入UIView子类的代码片段到你的控制器并发送becomeFirstResponder和resignFirstResponder消息给self而不是UIView子类。
一个基于第一个答案的swif挑逗版本!
override func motionEnded(_ motion: UIEventSubtype, with event: UIEvent?) {
if ( event?.subtype == .motionShake )
{
print("stop shaking me!")
}
}
推荐文章
- 是否有可能更新一个本地化的故事板的字符串?
- 以编程方式获取Bundle Identifier
- 为iPad和iPhone设计输入按钮
- 如何在我的iPhone应用程序中使用NSError ?
- 我的预发行应用已经在iTunes Connect中“处理”了一周多,这是怎么回事?
- Xcode iOS项目只显示“我的Mac 64位”,但不显示模拟器或设备
- Objective-C中的自动引用计数不能防止或减少什么样的泄漏?
- 在Xcode 9中如何从打开的多个模拟器中退出或关闭单个模拟器?
- 如何使用Swift播放声音?
- UINavigationBar自定义返回按钮没有标题
- 如何精确地以毫秒为单位记录方法的执行时间?
- 在整个UIWindow中获取UIView的位置
- 如何解散ViewController在Swift?
- 保存字符串到NSUserDefaults?
- 什么是NSLocalizedString等效在Swift?