Change orientation with NSNotificationCenter and UIDeviceOrientation - ios

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.

Related

How to detect volume button press on iOS 9?

I searched the solution for hours and it seems that AVSystemController_SystemVolumeDidChangeNotification should work. But after I finished the code I didn't see any callback when pressing the volume button. Here is my code:
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(volumeChanged:)
name:#"AVSystemController_SystemVolumeDidChangeNotification"
object:nil];
NSLog(#"init finished");
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)volumeChanged:(NSNotification *)notification
{
float volume =
[[[notification userInfo]
objectForKey:#"AVSystemController_AudioVolumeNotificationParameter"]
floatValue];
NSLog(#"current volume = %f", volume);
}

Objective C iOS 9 lock viewController portrait orientation

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.

iPad UIKeyboard Hide / Resign / Dismiss Button Event Handler?

Can you see the button in the bottom right of the iPad keyboard?
Well I want access to the event handler for that button, Because, I have some logic that I need to administer when specifically THAT button is pressed.
My attempted solution included using the UIKeyboardWillHideNotification notification like so:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(hideKeyboardTapped:)
name:UIKeyboardWillHideNotification
object:nil];
However this is called everytime the keyboard is dismissed, including when search cancel button is pressed, with a gesture tap on the background, etc; all of which have slightly different logic.
So I just need to have one set of logic for when that specific "hide keyboard" button is pressed.
The UIKeyboard is activated by a UISearchBar (for those of you who need extra info).
Any help would be greatly appreciated; and I'll answer any questions you may have.
There is not an official, Apple-sanctioned way to do this.
If you don't mind mucking around with private classes, which could get you rejected from the App Store, there is an unsupported method. Basically, you listen for changes to the keyboard's activeKey property, and if the new active key has a name of "Dismiss-Key", then the dismiss key was tapped:
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self)
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardDidShow:) name:UIKeyboardDidShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
}
return self;
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if ([keyPath isEqualToString:#"activeKey"])
{
id activeKey = [object valueForKey:keyPath];
NSString *keyName = [activeKey valueForKey:#"name"];
if ([keyName isEqualToString:#"Dismiss-Key"])
{
[self didTapDismissKey];
}
}
else
{
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
}
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void)keyboardDidShow:(NSNotification *)notification
{
// Search for the UIKeyboardLayoutStar class, which seems to manage layout for the keyboard, and observe its activeKey property
UIWindow *topWindow = [UIApplication sharedApplication].windows.lastObject;
[self traverseViewHierarchyWithView:topWindow block:^(UIView *view, BOOL *stop) {
if ([view isKindOfClass:NSClassFromString(#"UIKeyboardLayoutStar")])
{
[view addObserver:self forKeyPath:#"activeKey" options:0 context:NULL];
}
}];
}
- (void)keyboardWillHide:(NSNotification *)notification
{
// Don't forget to remove the controller as an observer!
UIWindow *topWindow = [UIApplication sharedApplication].windows.lastObject;
[self traverseViewHierarchyWithView:topWindow block:^(UIView *view, BOOL *stop) {
if ([view isKindOfClass:NSClassFromString(#"UIKeyboardLayoutStar")])
{
[view removeObserver:self forKeyPath:#"activeKey"];
}
}];
}
- (BOOL)traverseViewHierarchyWithView:(UIView *)view block:(void (^)(UIView *, BOOL *))block
{
BOOL stop = NO;
block(view, &stop);
if (stop)
{
return YES;
}
for (UIView *subview in view.subviews)
{
if ([self traverseViewHierarchyWithView:subview block:block])
{
return YES;
}
}
return NO;
}
- (void)didTapDismissKey
{
NSLog(#"Dismiss key tapped");
}
Tested on the iOS 7 iPad simulator and it works.
I don't know if you can put a listener to a single button of the keyboard, but you can try to set some Booleans on the views, that can turn on/off the events that you want or don't want to handle (I would approach it like that), for example:
Add a custom notification observer/listener at the class where you
want to execute the method of the event.
Add the Apple default Keyboard Hide listener on the controller where the notification will be triggered.
Then, on the views that can trigger the event... Set the booleans to activate/deactivate the event action
#Some Other Class
-(void)viewWillAppear:(BOOL)animated{
[[NSNotificationCenter defaultCenter]addObserver:self
selector:#selector(doSomething)
name:#"doSomethingNotification"
object:nil];
}
-(void)viewWillDisappear:(BOOL)animated{
[[NSNotificationCenter defaultCenter] removeObserver:self name:#"doSomethingNotification" object:nil];
}
#Trigger Class
-(void)viewWillAppear:(BOOL)animated{
self.isNotificationNeeded = NO;
[[NSNotificationCenter defaultCenter]addObserver:self
selector:#selector(onKeyboardHide:)
name:UIKeyboardWillHideNotification
object:nil];
}
-(void)viewWillDisappear:(BOOL)animated{
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil];
}
-(void)onKeyboardHide:(id)sender{
//When your event is Happening
if (self.isNotificationNeeded == YES) {
NSNotification *n = [NSNotification notificationWithName:#"doSomethingNotification" object:nil];
[[NSNotificationCenter defaultCenter] postNotification:n];
self.isNotificationNeeded = NO;
}
}
-(void)userClickedCancelButton{
//If this is a keyboard hide event that you don't want to trigger
self.isNotificationNeeded = NO;
}
//SearchBarDelegate
-(BOOL)searchBarShouldBeginEditing:(UISearchBar *)searchBar{
self.isNotificationNeeded = YES; //If your event can happen from here
return YES;
}

Can't dismiss MPMoviePlayerViewController when Home Button or Power Button pressed

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

UITextField not scrolling into view until edited

I have a UITextField embedded in a UIScrollView, and I want the text field to scroll up to be visible when the keyboard is active. I tried the top answer in How to make a UITextField move up when keyboard is present? but it seems that it does not work with auto-layout, so instead I took the code from the apple docs. This almost works, but its not scrolling the view until the user actually enters some data, rather than when the keyboard actually appears.
Here's what I'm doing - is there something obviously wrong?
// Call this method somewhere in your view controller setup code.
- (void)registerForKeyboardNotifications
{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWillShow:)
name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWillBeHidden:)
name:UIKeyboardWillHideNotification object:nil];
}
// Called when the UIKeyboardDidShowNotification is sent.
- (void)keyboardWillShow:(NSNotification*)aNotification
{
NSDictionary* info = [aNotification userInfo];
CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, kbSize.height, 0.0);
self.scrollView.contentInset = contentInsets;
self.scrollView.scrollIndicatorInsets = contentInsets;
// If active text field is hidden by keyboard, scroll it so it's visible
// Your application might not need or want this behavior.
CGRect aRect = self.view.frame;
aRect.size.height -= kbSize.height;
if (!CGRectContainsPoint(aRect, self.activeField.frame.origin) ) {
[self.scrollView scrollRectToVisible:self.activeField.frame animated:YES];
}
}
// Called when the UIKeyboardWillHideNotification is sent
- (void)keyboardWillBeHidden:(NSNotification*)aNotification
{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.3];
UIEdgeInsets contentInsets = UIEdgeInsetsZero;
self.scrollView.contentInset = contentInsets;
self.scrollView.scrollIndicatorInsets = contentInsets;
[UIView commitAnimations];
}
- (void)textFieldDidBeginEditing:(UITextField *)textField {
NSLog(#"textFieldDidEndEditing");
self.activeField = textField;
}
- (void)textFieldDidEndEditing:(UITextField *)textField
{
NSLog(#"textFieldDidEndEditing");
self.activeField = nil;
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self registerForKeyboardNotifications];
}
Try this,
ViewController.h
bool keyboardIsShown;
UITapGestureRecognizer *tapGesture;
ViewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(dismissKeyboard)];
tapGesture.cancelsTouchesInView = NO;
[self.view addGestureRecognizer:tapGesture];
scrollView.contentSize =CGSizeMake(0, self.view.frame.size.height+50);
// register for keyboard notifications
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWillShow:)
name:UIKeyboardWillShowNotification
object:self.view.window];
// register for keyboard notifications
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWillHide:)
name:UIKeyboardWillHideNotification
object:self.view.window];
keyboardIsShown = NO;
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
// unregister for keyboard notifications while not visible.
[[NSNotificationCenter defaultCenter] removeObserver:self
name:UIKeyboardWillShowNotification
object:nil];
// unregister for keyboard notifications while not visible.
[[NSNotificationCenter defaultCenter] removeObserver:self
name:UIKeyboardWillHideNotification
object:nil];
}
///// KEYBOARD
- (void) moveView:(float) yPos
{
[scrollView setContentOffset:CGPointMake(0, yPos) animated:YES];
}
- (void)keyboardWillHide:(NSNotification *)n
{
keyboardIsShown = NO;
[self.view removeGestureRecognizer:tapGesture];
[self moveView:0.0];
}
- (void)keyboardWillShow:(NSNotification *)n
{
if (keyboardIsShown)
{
return;
}
keyboardIsShown = YES;
[self.view addGestureRecognizer:tapGesture];
[self moveView:255.0];
}
// method to hide keyboard when user taps on a scrollview
-(void)dismissKeyboard
{
[self.view endEditing:YES];
}
Try the code below:
-(void)keyboardWillShow:(id)sender
{
if ([orientation==#"Landscape"])
[loginScrollView setContentSize:CGSizeMake(480, 620)];
else
[loginScrollView setContentSize:CGSizeMake(320, 670)];
}
and while editing the text use this
- (void)textFieldDidBeginEditing:(UITextField *)textField {
if ([orientation == #"Landscape"]) {
if (textField == usernameTextField)
[loginScrollView setContentOffset:CGPointMake(xValue, 200) animated:YES];
if (textField == passwordTextField)
[loginScrollView setContentOffset:CGPointMake(xValue, 220) animated:YES];
}
else{
if (textField == usernameTextField)
[loginScrollView setContentOffset:CGPointMake(xValue, 168) animated:YES];
if (textField == passwordTextField)
[loginScrollView setContentOffset:CGPointMake(xValue, 172) animated:YES];
}
}

Resources