motionBegan:withEvent: not called in AppDelegate in iOS 10
Asked Answered
R

3

9

I used to detect a shake motion from the AppDelegate by simply implementing this method:

- (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event {
    NSLog(@"shake shake shake");
}

which works fine in iOS 8 and 9. However it doesn't work in iOS 10 anymore. I also tried adding

- (BOOL)canBecomeFirstResponder {
        return YES;
}

but that didn't help. This works fine in the UIViewControllers though. Did something change in iOS 10, or is it just a bug?

Ric answered 15/9, 2016 at 19:1 Comment(0)
T
7

I had the same issue as you. Instead of implementing it on AppDelegate, I now use UIWindow, which works for me in iOS 8-10. Perhaps this is do-able for you as well?

extension UIWindow {

    override open var canBecomeFirstResponder: Bool {
        return true
    }

    override open func motionBegan(_ motion: UIEventSubtype, with event: UIEvent?) {
        if motion == .motionShake {
            //logic here
        }
    }
}

If you want to do it even cleaner, you might be able to set a specialized version of the UIWindow on the application.

Televisor answered 22/9, 2016 at 14:2 Comment(1)
Thanks @jayjunck. I fixed it in my code by moving this logic into the root view controller. I'm sure there are a lot of workarounds, but they still don't explain why it is not working in AppDelegate. AppDelegate is a UIResponder, so it should work...Ric
I
3

I had a similar issue and I tried @jayjunck's answer but Xcode thrown Method does not override any method from its superclass. I fixed it by replacing public with open to access and override motionBegan function In Swift 3,

  • An open class is accessible and subclassable outside of the defining module. An open class member is accessible and overridable outside of the defining module.

  • A public class is accessible but not subclassable outside of the defining module. A public class member is accessible but not overridable outside of the defining module.

enter code here

extension UIWindow {
override open func motionBegan(_ motion: UIEventSubtype, with event: UIEvent?) {
        super.motionBegan(motion, with: event)

        guard motion == UIEventSubtype.motionShake else { 
            return 
        }

        // Shake is detected 
    }
}

Swift 5

extension UIWindow {
        open override func motionBegan(_ motion: UIEvent.EventSubtype, with event: UIEvent?) {
            super.motionBegan(motion, with: event)

            guard motion == UIEvent.EventSubtype.motionShake else {
                return
            }

            // Shake is detected
        }
}
Impure answered 1/12, 2016 at 6:57 Comment(0)
S
-4

You should override motionBegan method in (all) View Controller(s).

Sarcoma answered 16/9, 2016 at 11:36 Comment(1)
It works fine in view controllers, it's not the problem. I need it to work in the AppDelegate.Ric

© 2022 - 2024 — McMap. All rights reserved.