I have a problem with my app. I cannot lock the orientation of my app. All I need to do is to lock one view controller to landscape mode and the rest are portrait.
This is hierarchy of my app.
*Navigation Controller
*TabBarController
*ViewControllers
You only have to return NO from shouldAutorotate and the landscape orientation from supportedInterfaceOrientation in the one you want to be in landscape.
On the other, return NO too from shouldAutorotate method and portrait orientations mask from supportedInterfaceOrientation.
In all the viewControllers :
-(BOOL)shouldAutorotate {
return NO;
}
In the one you want in landscape :
- (NSUInteger)supportedInterfaceOrientations{
return UIInterfaceOrientationMaskLandscape;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
return UIInterfaceOrientationLandscapeLeft;
}
In the controllers you want in portrait :
- (NSUInteger)supportedInterfaceOrientations{
return UIInterfaceOrientationMaskPortrait;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
return UIInterfaceOrientationPortrait;
}
Use below 2 this methods to lock device orientation to landscape.
- (NSUInteger)supportedInterfaceOrientations{
[super supportedInterfaceOrientations];
return (UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight);
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
if (interfaceOrientation==UIInterfaceOrientationLandscapeLeft || interfaceOrientation==UIInterfaceOrientationLandscapeRight)
{
return YES;
}
// Return YES for supported orientations
return NO;
}
With NavigationController
-(BOOL)shouldAutorotate
-(NSUInteger)supportedInterfaceOrientations
-(UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
these method are never called , if you use 'show segue(push)'.
change segue 'showDetail' instead 'show'
Related
I want to lock single viewcontroller in iPhone and iPad.
This below code is working perfectly in iPhone 4,5,6 iPad, iPad 2 ,iPad retina.
But not working in iPad pro.
#implementation UINavigationController (Orientation)
-(NSUInteger)supportedInterfaceOrientations
{
return [self.topViewController supportedInterfaceOrientations];
}
-(BOOL)shouldAutorotate
{
return YES;
}
#end
This above code is written in my view controller which view controller i do not want to rotate.
Write this below code in view controller, which view controller u want to lock in portrait mode
#implementation UINavigationController (Orientation)
-(NSUInteger)supportedInterfaceOrientations
{
return [self.topViewController supportedInterfaceOrientations];
}
-(BOOL)shouldAutorotate
{
return YES;
}
#end
#pragma mark Orientation
-(BOOL)shouldAutorotate
{
[super shouldAutorotate];
return NO;
}
-(NSUInteger) supportedInterfaceOrientations {
[super supportedInterfaceOrientations];
// Return a bitmask of supported orientations. If you need more,
// use bitwise or (see the commented return).
return UIInterfaceOrientationMaskPortrait;
// return UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskPortraitUpsideDown;
}
- (UIInterfaceOrientation) preferredInterfaceOrientationForPresentation {
[super preferredInterfaceOrientationForPresentation];
// Return the orientation you'd prefer - this is what it launches to. The
// user can still rotate. You don't have to implement this method, in which
// case it launches in the current orientation
return UIInterfaceOrientationPortrait;
}
And now do this below changes in your plist file
Write this in your view controller which you don't want to rotate
This will prevent any rotation.
The view controller class you don't want to rotate should have this.
- (BOOL)shouldAutorotate
{
return NO;
}
The containing navigation controller class should have this.
- (BOOL)shouldAutorotate
{
return [self.topViewController shouldAutoRotate];
}
This will only rotate to portrait
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait;
}
I'm trying to keep UITableViewcontroller in Portrait orientation. Hence, I don't want to rotate to Landscape mode. I added below method. But it didn't help, notice I'm using iOS 8:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
if(interfaceOrientation== UIInterfaceOrientationPortrait)
{
return YES;
}else
{
return NO;
}
}
Notice: I'm calling the UITableView through UINavigationController
UINavigationController *navigationController = [[UINavigationController alloc]
initWithRootViewController:svc];
// configure the new view controller explicitly here.
[self presentViewController:navigationController animated:YES completion: nil];
shouldAutorotateToInterfaceOrientation: has been deprecated since iOS 6.0. You should be using supportedInterfaceOrientations and shouldAutorotate.
Here's how you do it:
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return UIInterfaceOrientationPortrait;
}
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait;
}
- (BOOL)shouldAutorotate
{
return NO;
}
EDIT - for UINavigationController
This is one possible way to do it:
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
if ([self.visibleViewController isKindOfClass:[UITableViewController class]])
return UIInterfaceOrientationPortrait;
else
return [super preferredInterfaceOrientationForPresentation];
}
- (NSUInteger)supportedInterfaceOrientations
{
if ([self.visibleViewController isKindOfClass:[UITableViewController class]])
return UIInterfaceOrientationMaskPortrait;
else
return [super supportedInterfaceOrientations];
}
- (BOOL)shouldAutorotate
{
if ([self.visibleViewController isKindOfClass:[UITableViewController class]])
return NO;
else
return [super shouldAutorotate];
}
Note that you can't force the device orientation, so if the app is in landscape and you then push the table view controller, it will still be in landscape. There are a number of ways to handle this:
Block the user from opening the table view controller by displaying an alert asking them to rotate the device first.
Hide the table view and show a label with a message (or some other indicator) to tell the user to rotate their device.
Handle both orientations.
shouldAutorotateToInterfaceOrientation: is depricated. Instead, use:
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait;
}
- (BOOL)shouldAutorotate
{
return NO;
}
I'm using a subclass of UINavigationController to manage rotations for my app.
#implementation rotatingNavigationController
- (BOOL)shouldAutorotate
{
return [self.topViewController shouldAutorotate];
}
- (NSUInteger)supportedInterfaceOrientations
{
return [self.topViewController supportedInterfaceOrientations];
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return [self.topViewController preferredInterfaceOrientationForPresentation];
}
In my first view I only allow portrait orientation:
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait;
}
I push to a new view controller using a push segue created in the storyboard. The new view controller supports all interface orientations:
- (BOOL)shouldAutorotate
{
return YES;
}
- (NSUInteger)supportedInterfaceOrientations{
return UIInterfaceOrientationMaskAll;
}
The new view controller ALWAYS loads in portrait, no matter what orientation the device is held in. If I physically turn the device to portrait mode and back to landscape after the view loads, it rotates correctly. How can I correct this, I need the view to load in whatever orientation the device is held in when the view loads?
When you are push the newcontroller. check the interfaceorientation of statusbar then:
-(BOOL)shouldAutorotate
{
if(isPushingViewVC)
return NO
return YES;
}
And
- (NSUInteger)supportedInterfaceOrientations
{
if(isPushingViewVC)
{
switch ([UIApplication sharedApplication].statusBarOrientation)
{
case UIInterfaceOrientationLandscapeLeft:
return UIInterfaceOrientationMaskLandscapeLeft;
break;
case UIInterfaceOrientationPortrait:
return UIInterfaceOrientationMaskPortrait;
break;
case UIInterfaceOrientationPortraitUpsideDown:
return UIInterfaceOrientationMaskPortraitUpsideDown;
break;
default:
return UIInterfaceOrientationMaskLandscape;
break;
}
}
return UIInterfaceOrientationMaskAll;
}
I have embedded a UIViewController in a UINavigationController. The orientation of the view of this controller is set to Portait. When I push a new view on this UIViewController, which is landscape only, the new view is being shown portrait as well, instead of it's orientation landscape.
I have tried to subclass the UINavigationController and added the following methods like this:
- (BOOL)shouldAutorotate {
return self.topViewController.shouldAutorotate;
}
- (NSUInteger)supportedInterfaceOrientations {
return self.topViewController.supportedInterfaceOrientations;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return self.topViewController.preferredInterfaceOrientationForPresentation;
}
In the rootViewController (LoginViewController) I did this:
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return UIInterfaceOrientationPortrait;
}
- (BOOL)shouldAutorotate
{
return YES;
}
In the pushViewController (A custom ViewController) I did this:
- (NSUInteger)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskLandscape;
}
-(BOOL)shouldAutorotate {
return YES;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return UIInterfaceOrientationLandscapeRight | UIInterfaceOrientationLandscapeLeft;
}
I'm using a storyboard and a push segue between them. I know that the problem lies in the push segue which leads to an taking over of the orientation of the topviewcontroller which is portrait and the pushViewController is landscape. Does anyboy know workarounds?
Any help is thankfully appreciated. Else I should drop the navVC and perform a modal segue.
KR
Try this code :
In AppDelegate.m class write below code.
#pragma mark Orientation Code
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
NSUInteger orientations = UIInterfaceOrientationMaskAll;
if (self.window.rootViewController) {
UIViewController* presented = [[(UINavigationController *)self.window.rootViewController viewControllers] lastObject];
orientations = [presented supportedInterfaceOrientations];
}
return orientations;
}
And next if you don't want orientation of the particular class for example
Stop orientation viewController.m
#pragma mark Orientation
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return UIInterfaceOrientationPortrait;
}
- (BOOL)shouldAutorotate
{
return NO;
}
final thing to change project device orientation of project Target.
Ex : Project TARGETS --> Device Orientation -- > select All (Portrait, UpSide Down, Landscape Left, Landscape Right)
I have a scenario in which I have a UITabbarController with 5 tabs. Each tab contains a UINavigationController.
Now in one of the UINavigationController rootViewController, when I select an option, another viewcontroller is pushed. Now I want the another view controller to be Landscape only.
Following is the code of my UITabBarController n UINavigationController category for Orientation
#implementation UITabBarController (rotation)
-(BOOL)shouldAutorotate
{
if ([self.selectedViewController respondsToSelector:#selector(shouldAutorotate)]) {
return [self.selectedViewController shouldAutorotate];
}
else {
return YES;
}
}
- (NSUInteger)supportedInterfaceOrientations
{
if ([self.selectedViewController respondsToSelector:#selector(supportedInterfaceOrientations)]) {
return [self.selectedViewController supportedInterfaceOrientations];
}
else if(DEVICE_IS_IPAD)
return UIInterfaceOrientationMaskAll;
else
return UIInterfaceOrientationMaskPortrait;
}
-(UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
if ([self.selectedViewController respondsToSelector:#selector(supportedInterfaceOrientations)]) {
return [self.selectedViewController preferredInterfaceOrientationForPresentation];
}
return 0;
}
#end
#implementation UINavigationController (AutoRotationForwarding)
-(BOOL)shouldAutorotate
{
if ([self.topViewController respondsToSelector:#selector(shouldAutorotate)]) {
return [self.topViewController shouldAutorotate];
}
else {
return YES;
}
}
-(NSUInteger) supportedInterfaceOrientations {
if([self.topViewController respondsToSelector:#selector(supportedInterfaceOrientations)])
{
return [self.topViewController supportedInterfaceOrientations];
}
return UIInterfaceOrientationMaskPortrait;
}
-(UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
if ([self.topViewController respondsToSelector:#selector(supportedInterfaceOrientations)]) {
return [self.topViewController preferredInterfaceOrientationForPresentation];
}
return UIInterfaceOrientationPortrait | UIInterfaceOrientationLandscapeLeft | UIInterfaceOrientationLandscapeRight | UIInterfaceOrientationPortraitUpsideDown;
}
#end
and the code for the ViewController which I want to be Landscape only is :
-(BOOL)shouldAutorotate
{
return YES;
}
-(NSUInteger)supportedInterfaceOrientations
{
if(DEVICE_IS_IPAD)
return UIInterfaceOrientationMaskLandscape;
else
return UIInterfaceOrientationMaskPortrait;
}
-(UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return UIInterfaceOrientationLandscapeLeft;
}
The Main issue is preferredInterfaceOrientationForPresentation is not at all called for UITabbarController or UINavigationBarController or even the view controller which I want to show.
Could you please let me know what am I doing wrong?
Thanks.
May be you forgot to addsupportedInterfaceOrientationsForWindow to your AppDelegate?
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window{
return UIInterfaceOrientationMaskAll;
}
Beware of nil. I was following a similar approach of subclassing UINavigationController to relay the rotation messages to the topViewController. It worked great except the time the application launched. When you launch the application there is no topViewController (yet) but the OS needs to determine the supported orientation NOW AND for the the top-most viewController (the UINavigationController). If you fail to to provide an answer at the right time the UINavigationController will appear in the wrong orientation.
Note: PreferredInterfaceOrientationForPresentation is not called for UINavigationController
If your are using a UINavigationController as the root window
controller, it will be its shouldAutorotate &
supportedInterfaceOrientations which would be called.
iOS6: supportedInterfaceOrientations not working (is invoked but the interface still rotates)