Home > Articles > Mobile Application Development & Programming

  • Print
  • + Share This
This chapter is from the book

Detecting Shakes Using Motion Events

When the iPhone detects a motion event, it passes that event to the current first responder, the primary object in the responder chain. Responders are objects that can handle events. All views and windows are responders and so is the application object.

The responder chain provides a hierarchy of objects, all of which can respond to events. When an object toward the start of the chain receives an event, that event does not get passed further down. The object handles it. If it cannot, that event can move on to the next responder.

Objects often become the first responder by declaring themselves to be so, via becomeFirstResponder. In this snippet, a UIViewController ensures that it becomes the first responder whenever its view appears onscreen. Upon disappearing, it resigns the first responder position:

- (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];
}

First responders receive all touch and motion events. The motion callbacks mirror UIView touch callback stages. The callback methods are as follows:

  • motionBegan:withEvent:—This callback indicates the start of a motion event. At the time of writing this book, there was only one kind of motion event recognized: a shake. This may not hold true for the future, so you might want to check the motion type in your code.
  • motionEnded:withEvent:—The first responder receives this callback at the end of the motion event.
  • motionCancelled:withEvent:—As with touches, motions can be canceled by incoming phone calls and other system events. Apple recommends that you implement all three motion event callbacks (and, similarly, all four touch event callbacks) in production code.

The following snippet shows a pair of motion callback examples. If you test this on a device, you can notice several things. First, the began and ended events happen almost simultaneously from a user perspective. Playing sounds for both types is overkill. Second, there is a bias toward side-to-side shake detection. The iPhone is better at detecting side-to-side shakes than the front-to-back and up-down versions. Finally, Apple’s motion implementation uses a slight lockout approach. You cannot generate a new motion event until a second or so after the previous one was processed. This is the same lockout used by Shake to Shuffle and Shake to Undo events:

- (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];
}
  • + Share This
  • 🔖 Save To Your Account