当有人摇晃iPhone时,我想做出反应。我并不特别在意他们是如何摇晃它的,只在意它在一瞬间被使劲地挥舞着。有人知道怎么检测吗?


当前回答

你需要通过accelerometer:didAccelerate: method检查加速度计,这是UIAccelerometerDelegate协议的一部分,检查这些值是否超过了震动所需的移动量的阈值。

在AppController底部的accelerometer:didAccelerate:方法中有一些不错的示例代码。m在GLPaint例子中,这个例子可以在iPhone开发者网站上找到。

其他回答

你需要通过accelerometer:didAccelerate: method检查加速度计,这是UIAccelerometerDelegate协议的一部分,检查这些值是否超过了震动所需的移动量的阈值。

在AppController底部的accelerometer:didAccelerate:方法中有一些不错的示例代码。m在GLPaint例子中,这个例子可以在iPhone开发者网站上找到。

在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!")
    }
}

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)];

这是你需要的基本委托代码:

#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>

最简单的解决方案是为你的应用程序派生一个新的根窗口:

@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];
    //…
}

如果你使用的是故事板,这可能会更棘手,我不知道你在应用委托中需要精确的代码。