检测摇晃手势 IOS Swift

52
我正在开发一款手势系统的应用程序,基本上如果我把iPhone向左转,我的应用程序就会执行一个功能,如果我把iPhone向右转,将会执行另一个功能,还有其他手势。
我不知道如何处理这个问题,我试图在谷歌上搜索但是没有结果,只有触摸手势而没有动作手势。
请问是否有人能提供教程帮助我?

我建议您寻找动作事件:https://developer.apple.com/library/ios/documentation/EventHandling/Conceptual/EventHandlingiPhoneOS/motion_event_basics/motion_event_basics.html - dalipsia
7个回答

84

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?")
    }
}

3
适用于 Swift 4 和 iOS 11! - John Pavley
难道不是必须先辞去第一响应者的吗?就像在这个回答的最后部分所示:https://stackoverflow.com/a/47449094/897007 - Dale

26

非常容易实现:

1)告诉iOS哪个视图控制器是响应链中的第一个:

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

2)以某种方式处理该事件:

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

25

Swift 5

只需将以下方法添加到 ViewController 中并执行代码即可

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

2
你应该重写canBecomeFirstResponder而不是becomeFirstResponder,这样才能生效。在我将其更改为canBecomeFirstResponder之前,它并没有起作用。 - Herbal7ea

16
这已针对IOS 12进行更新 - 请参阅 Apple Docs。您不再需要添加 becomeFirstResponder() 方法。只需将 motionEnded 函数添加到您的代码中即可。
override func motionEnded(_ motion: UIEvent.EventSubtype, with event: UIEvent?) 
{
    // code here
}

请提供关于 becomeFirstResponder 的证明或文档链接。 - Dominik Bucher

12

Swift 5
iOS 10+

UIApplicationUIViewControllerUIViewUIWindow默认都是UIResponder对象,这意味着它们都可以处理动作事件(如抖动)而不需要任何特殊配置。因此,只需覆盖相应的动作方法:

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

此外,您可以覆盖 motionBegan(_:with:)motionCancelled(_:with:) 方法。与覆盖某些触摸事件不同的是,无需调用super方法。


这是正确的答案! - Thread Pitt

4

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

}

这只对我有效。将canBecomeFirstResponder返回为true就成功了。 - Ammar Mujeeb

2

Speedy99的快速回答是Objective C版本。

- (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?");
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接