Felipe Neves
Felipe Neves

Reputation: 957

Detect shake gesture IOS Swift

I'm developing a app with a gesture system, basically if I turn the iPhone to left my app will do a function, if I turn the iPhone to Right, other function, with others gestures.

I don't have idea how to work with that, i'm trying search in google but not work, the result is only touch gesture and not motion gesture.

someone have a tutorial to help me?

Upvotes: 53

Views: 48302

Answers (8)

Akbar Khan
Akbar Khan

Reputation: 2415

First, check no other view or control is set as the first responder.

Make sure the view is in the window hierarchy.

viewDidAppear is the best place to make view first responder.

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    if self.becomeFirstResponder() {
        print("Became first responder")
    } else {
        print("Failed to become first responder")
    }
}

override var canBecomeFirstResponder: Bool {
    get {
        return true
    }
}

// Enable detection of shake motion
override func motionEnded(_ motion: UIEvent.EventSubtype, with event: UIEvent?) {
    if motion == .motionShake {
        print("You are currently shaking your phone?")
    }
}

Upvotes: 0

ctrl freak
ctrl freak

Reputation: 12405

Swift 5
iOS 10+

UIApplication, UIViewController, UIView, and UIWindow are all UIResponder objects by default which means they can all handle motion events, like shake, without any special configuration. Therefore, simply override the appropriate motion method:

class YourViewController: UIViewController {
    override func motionEnded(_ motion: UIEvent.EventSubtype, with event: UIEvent?) {
        if motion == .motionShake {
            print("device did shake")
        }
    }
}

Additionally, you can override motionBegan(_:with:) and motionCancelled(_:with:). And unlike overriding certain touch events, there is no need to call super.

Upvotes: 14

Speedy99
Speedy99

Reputation: 1761

Swift3 ios10:

override func viewDidLoad() {
    super.viewDidLoad()
    self.becomeFirstResponder() // To get shake gesture
}

// We are willing to become first responder to get shake motion
override var canBecomeFirstResponder: Bool {
    get {
        return true
    }
}

// Enable detection of shake motion
override func motionEnded(_ motion: UIEvent.EventSubtype, with event: UIEvent?) {
    if motion == .motionShake {
        print("Why are you shaking me?")
    }
}

Upvotes: 85

swiftBoy
swiftBoy

Reputation: 35783

Swift 5

Just add following methods to ViewController and execute the code

override func becomeFirstResponder() -> Bool {
    return true
}

override func motionEnded(_ motion: UIEvent.EventSubtype, with event: UIEvent?){
    if motion == .motionShake {
        print("Shake Gesture Detected")
        //show some alert here
    }
}

Upvotes: 25

user2168735
user2168735

Reputation: 489

Swift 5

class MyViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        self.becomeFirstResponder()
    }

    override var canBecomeFirstResponder: Bool {
        get {
            return true
        }
    }

    override func motionEnded(_ motion: UIEvent.EventSubtype, with event: UIEvent?) {
        if motion == .motionShake {
            print("shake")
        }
    }

}

Upvotes: 4

Howard Panton
Howard Panton

Reputation: 267

This has been updated for IOS 12 - see Apple Docs You no longer need to add becomeFirstResponder() method.

You just need to add motionEnded function to your code.

override func motionEnded(_ motion: UIEvent.EventSubtype, with event: UIEvent?) 
{
    // code here
}

Upvotes: 17

Prakash
Prakash

Reputation: 872

Speedy99's swift answer is in the Objective C version

- (void)viewDidLoad {
    [super viewDidLoad];
    [self becomeFirstResponder];
}

- (BOOL)canBecomeFirstResponder{
    return true;
}

- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event{
    if(event.subtype == UIEventSubtypeMotionShake){
       NSLog(@"Why are you shaking me?");
    }
}

Upvotes: 2

Ryan Dines
Ryan Dines

Reputation: 1037

Super easy to implement:

1) Let iOS know which view controller is the first in the responder chain:

override func viewDidLoad() {
    super.viewDidLoad()
    self.becomeFirstResponder()
}   
override func canBecomeFirstResponder() -> Bool {
    return true
}

2) Handle the event in some fashion:

override func motionEnded(motion: UIEventSubtype, withEvent event: UIEvent?) {
    if(event.subtype == UIEventSubtype.MotionShake) {
        print("You shook me, now what")
    }
}

Upvotes: 27

Related Questions