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


当前回答

查看GLPaint示例。

http://developer.apple.com/library/ios/#samplecode/GLPaint/Introduction/Intro.html

其他回答

首先,肯德尔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子类会这样吗?是因为窗户位于食物链的顶端吗?

在ViewController中添加以下方法。M文件,它的工作正常

    -(BOOL) canBecomeFirstResponder
    {
         /* Here, We want our view (not viewcontroller) as first responder 
         to receive shake event message  */

         return YES;
    }

    -(void) motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event
    {
            if(event.subtype==UIEventSubtypeMotionShake)
            {
                    // Code at shake event

                    UIAlertView *alert=[[UIAlertView alloc] initWithTitle:@"Motion" message:@"Phone Vibrate"delegate:self cancelButtonTitle:@"OK" otherButtonTitles: nil];
                    [alert show];
                    [alert release];

                    [self.view setBackgroundColor:[UIColor redColor]];
             }
    }
    - (void)viewDidAppear:(BOOL)animated
    {
             [super viewDidAppear:animated];
             [self becomeFirstResponder];  // View as first responder 
     }

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

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

在我的Diceshaker应用中:

// Ensures the shake is strong enough on at least two axes before declaring it a shake.
// "Strong enough" means "greater than a client-supplied threshold" in G's.
static BOOL L0AccelerationIsShaking(UIAcceleration* last, UIAcceleration* current, 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);
}

@interface L0AppDelegate : NSObject <UIApplicationDelegate> {
    BOOL histeresisExcited;
    UIAcceleration* lastAcceleration;
}

@property(retain) UIAcceleration* lastAcceleration;

@end

@implementation L0AppDelegate

- (void)applicationDidFinishLaunching:(UIApplication *)application {
    [UIAccelerometer sharedAccelerometer].delegate = self;
}

- (void) accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration {

    if (self.lastAcceleration) {
        if (!histeresisExcited && L0AccelerationIsShaking(self.lastAcceleration, acceleration, 0.7)) {
            histeresisExcited = YES;

            /* SHAKE DETECTED. DO HERE WHAT YOU WANT. */

        } else if (histeresisExcited && !L0AccelerationIsShaking(self.lastAcceleration, acceleration, 0.2)) {
            histeresisExcited = NO;
        }
    }

    self.lastAcceleration = acceleration;
}

// and proper @synthesize and -dealloc boilerplate code

@end

组织性可以防止震动事件多次触发,直到用户停止震动。

只要用这三种方法就可以了

- (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event{
- (void)motionCancelled:(UIEventSubtype)motion withEvent:(UIEvent *)event{
- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event{

要了解详细信息,您可以在那里查看完整的示例代码