Reputation: 977
I added the following code to my appDelegate.m
- (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event
{
}
- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event
{
if (motion == UIEventSubtypeMotionShake )
{
// User was shaking the device. Post a notification named "shake".
[[NSNotificationCenter defaultCenter] postNotificationName:@"shake" object:self];
}
}
- (void)motionCancelled:(UIEventSubtype)motion withEvent:(UIEvent *)event
{
}
- (void)shakeSuccess
{
// do something...
}
and then I added :
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
// INIT THE BACKGROUND PATH STRING
[self refreshFields];
[self.window addSubview:navController.view];
[self.window makeKeyAndVisible];
***[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(shakeSuccess) name:@"shake" object:nil];***
return YES;
}
When I start my app on my iPhone, the method named "shakeSuccess" doesn't called. What should I do to implement this function in my app? any idea?
Upvotes: 25
Views: 36135
Reputation: 34175
Swift detect global Shake motion
create custom UIWindow class
import UIKit
class CustomWindow : UIWindow {
override var canBecomeFirstResponder: Bool {
return true
}
override func motionBegan(_ motion: UIEvent.EventSubtype, with event: UIEvent?) {
guard motion == .motionShake else {
return
}
//logic is here
}
}
setup CustomWindow
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: CustomWindow!
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let windowScene = (scene as? UIWindowScene) else { return }
//inti view controller as you wish
//or if your storyboard has `Is Initial View Controller`
let storyboard = UIStoryboard(name: String(describing: SomeViewController.self), bundle: nil)
let vc = storyboard.instantiateInitialViewController()
window = CustomWindow(windowScene: windowScene)
window.rootViewController = vc
window.makeKeyAndVisible()
}
}
Upvotes: 0
Reputation: 358
I extended UIApplication class and added class reference to main: MyApplication.h
@interface MyApplication : UIApplication
@end
MyApplication.m
@implementation MyApplication
- (void) sendEvent:(UIEvent *)event
{
if( event && (event.subtype==UIEventSubtypeMotionShake))
{
AppDelegate *objAppDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
[objAppDelegate doWhatEver];
[super sendEvent:event];
}
else
{
[super sendEvent:event];
}
}
@end
And the last step in main.m
int main(int argc, char *argv[])
{
return UIApplicationMain(argc, argv, NSStringFromClass([MyApplication class]), NSStringFromClass([AppDelegate class]));
}
This works in all cases.
Upvotes: 3
Reputation: 2770
If you want to be able to detect the shake motion across the app, the best way is to override the class of your application with a custom class.
And then implement this in your custom application class
@implementation PSApplication
- (void)sendEvent:(UIEvent *)event
{
if ( event.type == UIEventTypeMotion && event.subtype == UIEventSubtypeMotionShake ) {
[[NSNotificationCenter defaultCenter] postNotificationName:@"shakeNotification" object:nil];
}
[super sendEvent:event];
}
@end
Upvotes: 14
Reputation: 287
You could do something like this...
Firstly...
Set the applicationSupportsShakeToEdit property in the App's Delegate:
- (void)applicationDidFinishLaunching:(UIApplication *)application {
application.applicationSupportsShakeToEdit = YES;
[window addSubview:viewController.view];
[window makeKeyAndVisible];
}
Secondly...
Add/Override canBecomeFirstResponder, viewDidAppear: and viewWillDisappear: methods in your View Controller:
-(BOOL)canBecomeFirstResponder {
return YES;
}
-(void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[self becomeFirstResponder];
}
- (void)viewWillDisappear:(BOOL)animated {
[self resignFirstResponder];
[super viewWillDisappear:animated];
}
Thirdly...
Add the motionEnded method to your View Controller:
- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event
{
if (motion == UIEventSubtypeMotionShake)
{
// your code
}
}
That should work if the first answer did not and this is only quickly typed not tested:)
Upvotes: 26
Reputation: 10776
This might help you...
https://stackoverflow.com/a/2405692/796103
He says that you should set the UIApplication
's applicationSupportsShakeToEdit
to
YES
. and override 3 methods in your VC:
-(BOOL)canBecomeFirstResponder {
return YES;
}
-(void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[self becomeFirstResponder];
}
- (void)viewWillDisappear:(BOOL)animated {
[self resignFirstResponder];
[super viewWillDisappear:animated];
}
The rest of your code is fine. (the -motionEnded:withEvent:
)
Upvotes: 59