I'm writing an ios swift app and I want to include a support for shaking the device. As for now I want to print a msg to the console when user shakes his phone. I found this tutorial http://www.ioscreator.com/tutorials/detect-shake-gesture-ios8-swift and it looks super easy, however there's one thing that bothers me.
I want it to work from any view in the app, not only a single one. So no matter where user currently is in the app - he should be able to invoke the shake method. Should I implement the method override func motionEnded(motion: UIEventSubtype, withEvent event: UIEvent) {
in every panel then? Or is there a way of implementing it once and populating it across the whole app?
First of all lets find out where these 'motion' methods come from, as docs say:
The UIResponder class defines an interface for objects that respond to and handle events. It is the superclass of UIApplication, UIView and its subclasses.. (https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIResponder_Class/)
The event-handling methods for motion events are:
func motionBegan(motion: UIEventSubtype, withEvent event: UIEvent?)
func motionCancelled(motion: UIEventSubtype, withEvent event: UIEvent?)
func motionEnded(motion: UIEventSubtype, withEvent event: UIEvent?)
So, as you see, to 'catch' motion events on every screen of the app - we should override these methods in these screens. Thanks God, with extensions - we can make it much easier :)
To incapculate 'motion' logic lets make a protocol and name it 'MotionDelegate':
protocol MotionDelegate {
func motionBegan(motion: UIEventSubtype, withEvent event: UIEvent?)
func motionCancelled(motion: UIEventSubtype, withEvent event: UIEvent?)
func motionEnded(motion: UIEventSubtype, withEvent event: UIEvent?)
}
And make an extension of UIViewController, conforming MotionDelegate protocol:
extension UIViewController:MotionDelegate {
override public func becomeFirstResponder() -> Bool {
return true
}
override public func motionBegan(motion: UIEventSubtype, withEvent event: UIEvent?) {
if motion == .MotionShake { print("Shaking motionBegan with event\(event)") }
}
override public func motionCancelled(motion: UIEventSubtype, withEvent event: UIEvent?) {
if motion == .MotionShake { print("Shaking motionCancelled with event\(event)") }
}
override public func motionEnded(motion: UIEventSubtype, withEvent event: UIEvent?) {
if motion == .MotionShake { print("Shaking motionEnded with event\(event)") }
}
}
In this way motion handling will be working on EVERY UIViewController instances of your appliction.
To handle motion event on some certain vc your should override it in its extension:
extension MotionViewController {
override func motionEnded(motion: UIEventSubtype, withEvent event: UIEvent?) {
if motion == .MotionShake {
print("MotionViewController Shaking motionEnded with event\(event)")
}
}
}
Hope it helps!