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.
Related
I want to change the orientation of specific ViewController in Xcode.
I make a,b,cViewController and change the orientation only cViewController to LandscapeRight. (a and b's orientation are Portrait)
But if I change the orientation on cViewController and move ViewController from c to b, b's orientation is also changed to LandscapeRight.
(screen transition is push)
code:
a and bViewController's DidLoad
NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationPortrait];
[[UIDevice currentDevice] setValue:value forKey:#"orientation"];
cViewController's DidLoad
NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeRight];
[[UIDevice currentDevice] setValue:value forKey:#"orientation"];
How can I change the orientation only cViewController?
step-1
create the one bool property in your appdelegate like , this
#property () BOOL restrictRotation;
and call the function
-(UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
if(self.restrictRotation)
return UIInterfaceOrientationMaskLandscape ;
else
return UIInterfaceOrientationMaskPortrait;
}
step-2
and import the appdelegate #import "AppDelegate.h" in C VC
on your C VC View Will appear, call like
-(void)viewWillAppear:(BOOL)animated{
// for rotate the VC to Landscape
[self restrictRotationwithNew:YES];
}
(void)viewWillDisappear:(BOOL)animated{
// rotate the VC to Portait
[self restrictRotationwithNew:NO];
[super viewWillDisappear:animated];
}
-(void) restrictRotationwithNew:(BOOL) restriction
{
AppDelegate* appDelegate = (AppDelegate*)[UIApplication sharedApplication].delegate;
appDelegate.restrictRotation = restriction;
}
Choice 2
on your C VC check the Orientation using the delegate function of UIDeviceOrientationDidChangeNotification
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(orientationChanged:) name:UIDeviceOrientationDidChangeNotification object:nil];
- (void)orientationChanged:(NSNotification *)notification{
[self adjustViewsForOrientation:[[UIApplication sharedApplication] statusBarOrientation]];
}
- (void) adjustViewsForOrientation:(UIInterfaceOrientation) orientation {
UIDeviceOrientation deviceOrientation = [[UIDevice currentDevice] orientation];
switch (deviceOrientation) {
case UIDeviceOrientationPortrait:
NSLog(#"orientationPortrait");
;
break;
case UIDeviceOrientationPortraitUpsideDown:
NSLog(#"UIDeviceOrientationPortraitUpsideDown");
break;
case UIDeviceOrientationLandscapeLeft:
NSLog(#"OrientationLandscapeLeft");
break;
case UIDeviceOrientationLandscapeRight:
NSLog(#"OrientationLandscapeRight");
break;
default:
break;
}
}
My app running only in landscape mode, but i want display one View in portrait mode. So i have created project using Unified storyboards (Xcode 6). My project is running only which are targeted in Deployment Info.
and my view controller
What I do wrong? Help me.
I faced the same issue few weeks ago. I created new UIViewController with portrait orientation. Later I realised that changing orientation is not enough, then I used this below code to change the orientation.Use the below code to change orientation.
-(void)viewWillAppear:(BOOL)animated
{
[self willAnimateRotationToInterfaceOrientation:[UIApplication sharedApplication].statusBarOrientation duration:.2];
[self awakeFromNib];
}
-(void)viewWillDisappear:(BOOL)animated {
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIDeviceOrientationDidChangeNotification
object:nil];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
{
if(is_iPad)
{
return YES;
}else
{
return (UIInterfaceOrientationIsPortrait(toInterfaceOrientation));
}
}
- (void)awakeFromNib
{
AppDelegate *delegate = (AppDelegate *)[[UIApplication sharedApplication]delegate];
delegate->isShowingLandscapeView=NO;
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(orientationChanged:)
name:UIDeviceOrientationDidChangeNotification
object:nil];
}
- (void)orientationChanged:(NSNotification *)notification
{
if (is_iPad) {
AppDelegate *delegate = (AppDelegate *)[[UIApplication sharedApplication]delegate];
UIDeviceOrientation deviceOrientation = [UIDevice currentDevice].orientation;
if (UIDeviceOrientationIsLandscape(deviceOrientation) &&
!delegate->isShowingLandscapeView)
{
yourPotraitViewController *ypvc =[[yourPotraitViewController alloc] initWithNibName:#"yourPotraitViewController" bundle:nil];
[self.navigationController pushViewController:objHomeLandscape animated:YES];
delegate->isShowingLandscapeView=YES;
// isShowingLandscapeView = YES;
}
else if (UIDeviceOrientationIsPortrait(deviceOrientation) &&
delegate->isShowingLandscapeView)
{
[self.navigationController popViewControllerAnimated:YES];
delegate->isShowingLandscapeView=NO;
}
}
}
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.
I've tried to following methods to force landscape on one my views:
- (NSUInteger)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskLandscape;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
return UIInterfaceOrientationLandscapeLeft;
}
- (BOOL)shouldAutorotate{
return YES;
}
Neither did work. Note that I'm testing on the simulator and on an iPad.
Thanks
Here is how I forced one of my views to be Landscape using NavigationViewController:
Implemented this answer: https://stackoverflow.com/a/12662433/2394787
Imported message in the View controller: objc/message.h
Added this line of code in the viewDidLoad method:
objc_msgSend([UIDevice currentDevice], #selector(setOrientation:), UIInterfaceOrientationLandscapeLeft);
Hope it helps someone.
The accepted answer doesn't seem to work on iOS 7.1.2. (It works on the simulator but does not work while running on a device.)
This seems to work though:
[[UIDevice currentDevice] setValue:[NSNumber numberWithInteger:UIInterfaceOrientationPortrait] forKey:#"orientation"];
[[UIDevice currentDevice] setValue:[NSNumber numberWithInteger:UIInterfaceOrientationLandscapeLeft] forKey:#"orientation"];
int shouldShowInLandscape = 0;
-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(forceToLandscape:)
name:#"yourNameNotification"
object:nil];
}
-(NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
{
return UIInterfaceOrientationMaskLandscapeLeft;
} else {
if(shouldShowInLandscape)
{
return UIInterfaceOrientationMaskLandscape;
}
return UIInterfaceOrientationMaskPortrait;
}
}
-(void) forceToLandscape:(NSNotification*) theNot
{
shouldShowInLandscape = [[theNot object] intValue];
}
// from the UIViewController
- (void)viewDidLoad
{
[super viewDidLoad];
[[NSNotificationCenter defaultCenter]
postNotificationName:#"yourNameNotification"
object:[NSString stringWithFormat:#"1"]];
}
-(void) viewDidDisappear:(BOOL)animated
{
[[NSNotificationCenter defaultCenter]
postNotificationName:#"yourNameNotification"
object:[NSString stringWithFormat:#"0"]];
}
// remove you notificationCenter
I have a simple view controller (SecondViewController) used to manage a UITextview
(I'm building a simple editor)
this is the code of the SecondViewController.h
#interface SecondViewController : UIViewController {
IBOutlet UITextView *textView;
}
#property (nonatomic,retain) IBOutlet UITextView *textView;
#end
and this is the SecondViewController.m
//
// EditorViewController.m
// Editor
//
// Created by elio d'antoni on 13/01/11.
// Copyright 2011 none. All rights reserved.
//
#implementation SecondViewController
#synthesize textView;
/*
// Implement loadView to create a view hierarchy programmatically, without using a nib.
- (void)loadView {
}
*/
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"uiViewBg.png"]];
textView.layer.borderWidth=1;
textView.layer.cornerRadius=5;
textView.layer.borderColor=[[UIColor darkGrayColor] CGColor];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillAppear:) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillDisappear:) name:UIKeyboardWillHideNotification object:nil];
}
-(void) matchAnimationTo:(NSDictionary *) userInfo {
NSLog(#"match animation method");
[UIView setAnimationDuration:[[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]];
[UIView setAnimationCurve:[[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue]];
}
-(CGFloat) keyboardEndingFrameHeight:(NSDictionary *) userInfo {
NSLog(#"keyboardEndingFrameHeight method");
CGRect keyboardEndingUncorrectedFrame =
[[ userInfo objectForKey:UIKeyboardFrameEndUserInfoKey ]
CGRectValue];
CGRect keyboardEndingFrame =
[self.view convertRect:keyboardEndingUncorrectedFrame
fromView:nil];
return keyboardEndingFrame.size.height;
}
-(CGRect) adjustFrameHeightBy:(CGFloat) change
multipliedBy:(NSInteger) direction {
NSLog(#"adjust method");
return CGRectMake(20,
57,
self.textView.frame.size.width,
self.textView.frame.size.height + change * direction);
}
-(void)keyboardWillAppear:(NSNotification *)notification {
NSLog(#"keyboard appear");
[UIView beginAnimations:nil context:NULL];
[self matchAnimationTo:[notification userInfo]];
self.textView.frame =
[self adjustFrameHeightBy:[self keyboardEndingFrameHeight:
[notification userInfo]]
multipliedBy:-1];
[UIView commitAnimations];
}
-(void)keyboardWillDisappear:(NSNotification *) notification {
NSLog(#"keyboard disappear");
[UIView beginAnimations:nil context:NULL];
[self matchAnimationTo:[notification userInfo]];
self.textView.frame =
[self adjustFrameHeightBy:[self keyboardEndingFrameHeight:
[notification userInfo]]
multipliedBy:1];
[UIView commitAnimations];
}
// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return YES;
}
(void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
(void)viewDidUnload {
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
(void)dealloc {
[super dealloc];
}
#end
the problem is that if load the view controller from a tab bar controller the textView doesn't resize when the keyboard appear, but the SAME code works if loaded as a single view based app. I hope I was clear enough.
I used the tabBar template provided by xcode no modifications.
Your code looks right, did notice you are not releasing "textView" in dealloc and "viewDidUnload" but this should make any difference.
I'd be checking the notications are received and everthing is wired up ie textView is not nil