How to change the orientation of specific ViewController in Xcode - ios

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

Related

How to fix orientation?

I need to fix orientation portrait or landscapeLeft like Youtube's full screen.
When a user click button, it was changed portrait or landscapeLeft.
and was fixed.
The user can control only by button.
accept Device orientation Portrait, Landscape Left in General
It's my code
AppDelegate
-(UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
if(restrictRotation)
return UIInterfaceOrientationMaskPortrait;
else
return UIInterfaceOrientationMaskLandscapeLeft;
}
ViewController
-(void) restrictRotation:(BOOL) restriction
{
AppDelegate* appDelegate = (AppDelegate*)[UIApplication sharedApplication].delegate;
appDelegate->restrictRotation = restriction;
}
- (IBAction)rotateOrientationAction:(id)sender
{
[self restrictRotation:NO];
if(isPortrait){
[[UIDevice currentDevice] setValue:#(UIInterfaceOrientationLandscapeLeft) forKey:#"orientation"];
self.myNewScrollViewHeight.constant = self.view.frame.size.height - self.naviBar.frame.size.height - self.horizMenu.frame.size.height;
self.portraitMenuView.hidden = YES;
}else{
[[UIDevice currentDevice] setValue:#(UIInterfaceOrientationPortrait) forKey:#"orientation"];
self.myNewScrollViewHeight.constant = self.view.frame.size.height * 0.5;
self.portraitMenuView.hidden = NO;
}
isPortrait = !isPortrait;
[self restrictRotation:YES];
}
If I click the button, it was changed landscapeLeft but not changed portrait again.
Thank you
Your condition is not satisfied for restrictRotation, please check below code to desire result.
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
isPortrait = YES;
}
-(void) restrictRotation:(BOOL) restriction
{
AppDelegate* appDelegate = (AppDelegate*)[UIApplication sharedApplication].delegate;
appDelegate.restrictRotation = restriction;
}
- (IBAction)rotateOrientationAction:(id)sender
{
if (isPortrait) {
[self restrictRotation:NO];
[[UIDevice currentDevice] setValue:#(UIInterfaceOrientationLandscapeLeft) forKey:#"orientation"];
} else {
[self restrictRotation:YES];
[[UIDevice currentDevice] setValue:#(UIInterfaceOrientationPortrait) forKey:#"orientation"];
}
isPortrait = !isPortrait;
}
Update :
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
isPortrait = YES;
}
- (IBAction)rotateOrientationAction:(id)sender
{
AppDelegate* appDelegate = (AppDelegate*)[UIApplication sharedApplication].delegate;
appDelegate.restrictRotation = NO;
[[UIDevice currentDevice] setValue:#(UIInterfaceOrientationPortrait) forKey:#"orientation"];
if (isPortrait)
{
[[UIDevice currentDevice] setValue:#(UIInterfaceOrientationLandscapeLeft) forKey:#"orientation"];
}
else
{
[[UIDevice currentDevice] setValue:#(UIInterfaceOrientationPortrait) forKey:#"orientation"];
}
isPortrait = !isPortrait;
}

How to force orientation of all screen to be in portrait mode if switch is on ?? if user rotate it should not change its orientation

It is an superclass file name Apporientationviewcontroller.h/m. And i am calling this super class in all other subclasses. So that if "isPortraitModeONN" is "ON"
then all the screen should work only in portrait mode. if user try to changes the device to landscape it should not rotate. it should be always in portrait mode if switch is "ON".. In my case while laughing the app it is in portrait mode. but if i rotate the screen it is changing towards landscape. but it should not change its orientation until turning OFF the switch in settings..
if(isPortraitModeONN)
{
[[UIDevice currentDevice] setOrientation:UIInterfaceOrientationPortrait];
}
else
{
if ([[UIDevice currentDevice] orientation] == UIDeviceOrientationLandscapeLeft){
[[UIDevice currentDevice] setOrientation:UIInterfaceOrientationLandscapeRight];
}
else if([[UIDevice currentDevice] orientation] == UIDeviceOrientationLandscapeRight)
{
[[UIDevice currentDevice] setOrientation:UIInterfaceOrientationLandscapeLeft];
}
else{
[[UIDevice currentDevice] setOrientation:UIInterfaceOrientationLandscapeRight];
}
}
This code works for me somewhat..
-(void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator: (id<UIViewControllerTransitionCoordinator>)coordinator
{
///if isPortraitMode On then force the orientation to portrait if it's other than Portrait
///else force the orientation to landscape
if (isPortraitModeONN)
{
[coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context)
{
// do whatever
UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
if (UIInterfaceOrientationIsLandscape(orientation)) {
///App is rotating to landscape, force it to portrait
NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationPortrait];
[[UIDevice currentDevice] setValue:value forKey:#"orientation"];
}
} completion:^(id<UIViewControllerTransitionCoordinatorContext> context)
{
}];
}
else{
[coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context)
{
// do whatever
UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
if (UIInterfaceOrientationIsPortrait(orientation)) {
///App is rotating to portrait, force it to landscape
NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeRight];
[[UIDevice currentDevice] setValue:value forKey:#"orientation"];
}
} completion:^(id<UIViewControllerTransitionCoordinatorContext> context)
{
}];
}
[super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
}
You can do like this-
Add - #property () BOOL isPortraitModeONN; in AppDelegate.h class.
Now code this in AppDelegate.m -
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.isPortraitModeONN=YES;
return YES;
}
-(UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
if(self.isPortraitModeONN)
return UIInterfaceOrientationMaskPortrait;
else
return UIInterfaceOrientationMaskLandscape;
}
Now Add IBAction of UIButton for changing orientation in Apporientationviewcontroller.m--
- (IBAction)changeOrientation:(id)sender {
if (allowedToRotate) {
allowedToRotate=NO;
AppDelegate* appDelegate = (AppDelegate*)[UIApplication sharedApplication].delegate;
appDelegate.isPortraitModeONN = NO;
NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeLeft];
[[UIDevice currentDevice] setValue:value forKey:#"orientation"];
}else{
allowedToRotate=YES;
AppDelegate* appDelegate = (AppDelegate*)[UIApplication sharedApplication].delegate;
appDelegate.isPortraitModeONN = YES;
NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationPortrait];
[[UIDevice currentDevice] setValue:value forKey:#"orientation"];
}
}
define in Apporientationviewcontroller.m BOOL allowedToRotate; default value is YES;
Goto Target -> Deployment info -> set device Orientation to portrait only
As par your question if you want to do this by tapping on button
Please try this code i am not sure about this it works on your project but it works for my dummy project
please try it
[[UIDevice currentDevice] setValue:
[NSNumber numberWithInteger: UIInterfaceOrientationPortrait]
forKey:#"orientation"];
change the device orientation for both buttons
You code should be like this,
AppDelegate.h
#property () BOOL restrictRotation;
-(UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window;
AppDelegate.m
-(UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
if(self.restrictRotation)
return UIInterfaceOrientationMaskLandscape; //you can change upsidedown etc
else
return UIInterfaceOrientationMaskPortrait; // you can change landscape right or left only
//this should be your initial app orientation because by default value of bool is false
}
SettingsViewController (from where you want to change whole app orientations)
-(void) restrictRotation:(BOOL) restriction
{
AppDelegate* appDelegate = (AppDelegate*)[UIApplication sharedApplication].delegate;
appDelegate.restrictRotation = restriction;
[appDelegate application:[UIApplication sharedApplication] supportedInterfaceOrientationsForWindow:self.view.window];
}
don't forget to import appdelegate.h ;)
And finally from your switch for changing orientation,
[self restrictRotation:YES]; // or NO
You can manipulate supportedInterfaceOrientationsForWindow as per requirement like you can set property as int instead of bool and can set multiple orientation for different int value.
hope this will help :)

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.

UIViewController animations wait until animation complete

I'm using this observer: UIDeviceOrientationDidChangeNotification to detect when user is changing the device orientation. When the orientation changed to landscape I present a new UIViewController or dismiss this UIViewController when he changes it back to portrait.
My problem starts when the user start rotating the device number of times and fast, then the application goes crazy until I get this error:
Warning: Attempt to present on whose view is not in the window hierarchy!`.
What is the best possible way to wait until the animation is over and then change the rotation?
This is what I'm using on the Presenting view controller:
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self beginDeviceOrientationListener];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void)beginDeviceOrientationListener
{
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(orientationChanged:) name:UIDeviceOrientationDidChangeNotification object:[UIDevice currentDevice]];
}
- (void)orientationChanged:(NSNotification *)notification
{
UIDevice *device = notification.object;
switch (device.orientation)
{
case UIDeviceOrientationLandscapeLeft:
case UIDeviceOrientationLandscapeRight:
{
TheViewControllerToPresent *viewController = [[TheViewControllerToPresent alloc] init];
[self presentViewController:viewController animated:YES completion:nil];
[[UIDevice currentDevice] setValue:[NSNumber numberWithInteger:UIInterfaceOrientationLandscapeRight] forKey:#"orientation"];
[[UIApplication sharedApplication] setStatusBarOrientation:[[[UIDevice currentDevice] valueForKey:#"orientation"] integerValue] animated:YES];
[[UIApplication sharedApplication] setStatusBarHidden:NO withAnimation:UIStatusBarAnimationSlide];
}
break;
default:
break;
}
}
This is what I'm using on the Presented view controller:
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self beginDeviceOrientationListener];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void)beginDeviceOrientationListener
{
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(orientationChanged:) name:UIDeviceOrientationDidChangeNotification object:[UIDevice currentDevice]];
}
- (void)orientationChanged:(NSNotification *)notification
{
UIDevice *device = notification.object;
switch (device.orientation)
{
case UIDeviceOrientationPortrait:
{
[self dismissViewControllerAnimated:YES completion:nil];
[[UIDevice currentDevice] setValue:[NSNumber numberWithInteger:UIInterfaceOrientationPortrait] forKey:#"orientation"];
[[UIApplication sharedApplication] setStatusBarOrientation:[[[UIDevice currentDevice] valueForKey:#"orientation"] integerValue] animated:YES];
}
break;
default:
break;
}
}
The most simplest solution that I am using myself is stopping the user from making any changes while the animation is in progress.
This is done by adding the following code when the animation starts:
[[UIApplication sharedApplication] beginIgnoringInteractionEvents];
[[UIDevice currentDevice] endGeneratingDeviceOrientationNotifications];
and to the completion handler:
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[UIApplication sharedApplication] endIgnoringInteractionEvents];
The user can rotate the device but the events won't be generated during the animation so the animations won't collide. However, when the animation ends, you should explicitly check the orientation:
UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
to see whether you should start another animation or not.

uisearch bar width is reduced when change orientation from landscape to portrait

I am using tableview with search bar display controller, it shows good in portait and landscape view, but rotate from landscape to portrait search bar size is reduced, how to change the original size
The first your should catch the orientation:
//AppDelegate.h
#interface AppDelegate : UIResponder <UIApplicationDelegate>
#property (nonatomic, unsafe_unretained) NSInteger isPortrait;
//AppDelegate.m
#synthesize isPortrait;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
isPortrait = 1;
}
Implementation state:
-(void)viewWillAppear:(BOOL)animated{
[[UIApplication sharedApplication] statusBarOrientation];
[[UIDevice currentDevice] orientation];
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(deviceRotated:) name:UIDeviceOrientationDidChangeNotification object:nil];
}
//methode deviceRotated
-(void)deviceRotated:(NSNotification*)notification{
AppDelegate *app = (AppDelegate *)[UIApplication sharedApplication].delegate;
UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
if(orientation == UIInterfaceOrientationLandscapeLeft || orientation == UIInterfaceOrientationLandscapeRight)
{
[self searchBarLandscape];
app.isPortrait = NO;
}
else{
[self searchBarPortrait];
app.isPortrait = YES;
}
}
- (BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation{
return YES;
}
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
AppDelegate * app = (AppDelegate *)[UIApplication sharedApplication].delegate;
if (toInterfaceOrientation == UIInterfaceOrientationPortraitUpsideDown || toInterfaceOrientation == UIInterfaceOrientationPortrait)
{
app.isPortrait = 1;
}
else if (toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft || toInterfaceOrientation == UIInterfaceOrientationLandscapeRight)
{
app.isPortrait = 0;
}
[self prepareSearchBarOrientation];
}
-(void)prepareSearchBarOrientation
{
AppDelegate * app = (AppDelegate *)[UIApplication sharedApplication].delegate;
if (app.isPortrait)
{
[self searchBarPortrait];//Set Frame here
}
else
{
[self searchBarLandscape];
}
}
Did you try setting the searchBar's frame in the rotation delegate methods or Try auto resizing in XIB.
See this for a better idea.

Resources