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?
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:)
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:)
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
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.
Related
After upgrade my project do iOS 9.2 my old code become obsolete
-(UIInterfaceOrientationMask)supportedInterfaceOrientations{
return UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskPortraitUpsideDown;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation{
return UIInterfaceOrientationPortrait;
}
And I found this ugly solution, after receive a rotation notification view set rotation (And repaint with animation my view controller):
-(void)didRotate:(NSNotification *)notification
{
[UIView animateWithDuration:0 animations:^{
NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationPortrait];
[[UIDevice currentDevice] setValue:value forKey:#"orientation"];
}];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(didRotate:)
name:UIDeviceOrientationDidChangeNotification
object:nil];
}
-(void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:YES];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIDeviceOrientationDidChangeNotification object:nil];
}
How can I lock orientation only in this ViewController?
You can use the below delegate method for the orientation and it can be applicable for the class where the code is being used. These 3 lines of code is fair enough to lock your orientation.
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
return (UIInterfaceOrientationMaskPortrait);
}
For iOS 9 and above
First Identify your base view controller
Suppose it is a Navigation Controller.
Property for Navigation Controller:
#property (strong, nonatomic) UINavigationController *mainNavigationController;
Replace the above with:
#property (strong, nonatomic) MainNavigationContrller *mainNavigationController;
Your MainNavigationContrller.m will look like the below:
#interface MainNavigationContrller ()
#end
#implementation MainNavigationContrller
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (BOOL)shouldAutorotate
{
return YES;
}
- (UIInterfaceOrientationMask)supportedInterfaceOrientations
{
if(IPHONE)
{
UIViewController *topVC = ((AppDelegate*)[[UIApplication sharedApplication] delegate]).yourNavigationController.topViewController;
if([topVC isKindOfClass:[yourViewController class]])
{
return UIInterfaceOrientationMaskPortrait;
}
}
return UIInterfaceOrientationMaskAll;
}
With this, you need not to remove your info.plist entries and we can block the orientation for specific view only.
THIS WORKED FOR ME.
I am attempting to hide/unhide the status bar programmatically upon a view appearing and disappearing. This was my first attempt (that worked), but it animates my UINavigationBar which I don't want to happen.
-(BOOL)prefersStatusBarHidden
{
return YES;
}
But this is essentially what I want to work, but it does absolutely nothing.
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[[UIApplication sharedApplication]setStatusBarHidden:YES withAnimation:UIStatusBarAnimationNone];
}
-(void)viewWillDisappear:(BOOL)animated
{
[[UIApplication sharedApplication]setStatusBarHidden:NO withAnimation:UIStatusBarAnimationNone];
[super viewWillDisappear:animated];
}
Instead of using setStatusBarHidden:withAnimation: you should return UIStatusBarAnimationNone from
- (UIStatusBarAnimation)preferredStatusBarUpdateAnimation
and call
[self setNeedsStatusBarAppearanceUpdate];
Complete code:
#property (nonatomic, assign, readwrite) BOOL visible;
- (BOOL)prefersStatusBarHidden {
return self.visible;
}
- (UIStatusBarAnimation)preferredStatusBarUpdateAnimation {
return UIStatusBarAnimationNone;
}
- (void)setVisible:(BOOL)visible {
_visible = visible;
[self setNeedsStatusBarAppearanceUpdate];
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
self.visible = YES;
}
- (void)viewWillDisappear:(BOOL)animated {
self.visible = NO;
[super viewWillDisappear:animated];
}
just add a simple line and your problem will solved.
[[UIApplication sharedApplication] setStatusBarHidden:status];
Why don´t work when I change the orientation of the simulator in xCode? I see equals the label on the ViewController all time and the NSLog doesn´t appear.
ViewController.m:
- (void)viewDidLoad
{
[self orientacionActual];
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(orientacionActual)
name:UIDeviceOrientationDidChangeNotification
object:nil];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(UIDeviceOrientation) orientacionActual
{
UIDeviceOrientation orientacionActual = [UIDevice currentDevice].orientation;
return orientacionActual;
}
- (void) cambiaOrientacion:(NSNotification *) notificación
{
if(UIDeviceOrientationIsLandscape([self orientacionActual]))
{
self.LabelEstoy.text = #"Landscape";
NSLog(#"Landscape");
} else if (UIDeviceOrientationIsPortrait([self orientacionActual]))
{
self.LabelEstoy.text = #"Portrait";
NSLog(#"Portrait");
}
}
Call UIApplicationDidChangeStatusBarOrientationNotification instead of device orientation changes. Also, I'm not sure what is your goal, but try to use this snippet:
Inside viewDidLoad:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(cambiaOrientacion:)
name:UIApplicationDidChangeStatusBarOrientationNotification
object:nil];
and below:
- (void)cambiaOrientacion:(NSNotification *)notificacion
{
UIInterfaceOrientation orientation = [[[notification userInfo]
objectForKey:UIApplicationStatusBarOrientationUserInfoKey] integerValue];
if (UIInterfaceOrientationIsLandscape(orientation))
{
self.LabelEstoy.text = #"Landscape";
NSLog(#"Landscape");
} else
{
self.LabelEstoy.text = #"Portrait";
NSLog(#"Portrait");
}
}
and orientacionActual method redudant in your code, and doesn't makes any sense.
Don't forget to add [[NSNotificationCenter defaultCenter] removeObserver:self] inside dealloc.
Basically, I have a MainViewController that presents a MPMoviePlayerViewControllerExtended and I want to dismiss MPMoviePlayerViewControllerExtended when user taps the Home Button or Power Button.
I tried this in MPMoviePlayerControllerExtended.m:
-(void)viewWillDisappear {
[self dismissMoviePlayerViewControllerAnimated];
}
-(void)viewDidDisappear {
[self dismissMoviePlayerViewControllerAnimated];
}
But it doesn't work, apparently they aren't called when Home or Power button is pressed.
Any help is appreciated.
try adding :(BOOL)animated
-(void)viewWillDisappear:(BOOL)animated {
[self dismissMoviePlayerViewControllerAnimated];
}
-(void)viewDidDisappear:(BOOL)animated {
[self dismissMoviePlayerViewControllerAnimated];
}
Also probably want to include the
[super viewWillDisappear:animated]
and
[super viewDidDisappear:animated]
in those somewhere too
-(void)viewWillDisappear:(BOOL)animated {
[self dismissMoviePlayerViewControllerAnimated];
[super viewWillDisappear:animated]
}
-(void)viewDidDisappear:(BOOL)animated {
[self dismissMoviePlayerViewControllerAnimated];
[super viewDidDisappear:animated]
}
Since both methods aren't called, I had to use Notifications.
In MPMoviePlayerViewControllerExtended.m
- (void)viewDidLoad
{
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(dismissModalViewControllerAnimated:)
name:UIApplicationDidEnterBackgroundNotification
object:nil];
}
I am trying to detect double tap in a uiwebview. following is the code. when i debug, debugger comes to initwithcoder but never to touchesbegan nor to selector function. why so ?
I am putting a UIWebView in my xib file and setting identity inspector class to MyWebView
#import "MyWebView.h"
#implementation MyWebView
- (void) initTap {
UITapGestureRecognizer *singleFingerDoubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleSingleFingerDoubleTap:)];
singleFingerDoubleTap.numberOfTouchesRequired = 1;
singleFingerDoubleTap.numberOfTapsRequired = 2;
[self addGestureRecognizer:singleFingerDoubleTap];
[singleFingerDoubleTap release];
}
- (id)initWithCoder:(NSCoder*)coder
{
if (self = [super initWithCoder:coder]) {
// Initialization code.
[self initTap];
}
return self;
}
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
// Initialization code.
[self initTap];
}
return self;
}
-(void)handleSingleFingerDoubleTap:(id)sender {
NSLog(#"Doulble click detected !");
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [[event allTouches] anyObject];
if (touch.tapCount == 2) {
//put you zooming action here
NSLog(#"Doulble click detected !");
}
}
- (void)dealloc {
[super dealloc];
}
#end
You just need to add delegate to the recognizer
singleFingerDoubleTap.delegate = self;
Then implement the following method to return YES.
#pragma mark Gesture recognizer delegate
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
return YES;
}
Don't forget to add conform declaration to your class file.
Like this
#interface ORWebViewController : UIViewController<UIGestureRecognizerDelegate>
In case, you want to override the default zooming action on double tap, this will guide you.
UPDATE:
Please do not consider above mentioned reference as the author has moved it.
You can find the references from Disabling default zoom effect.