10

I have an app with 9-10 screens. I embedded a UINavigationController into my view controller. I have few view controllers which I want set only portrait orientation: it means that rotating the device should not rotate these view controllers to landscape mode. I have tried the following solutions:

first:

   NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationPortrait];
   [[UIDevice currentDevice] setValue:value forKey:@"orientation"];

but screen still rotates to landscape.

Second: I created a custom view controller class as PortraitViewController and added the code below in PortraitViewController.m

@interface PortraitViewController ()
@end

@implementation PortraitViewController
- (BOOL)shouldAutorotate
{
    return YES;
}

- (NSUInteger)supportedInterfaceOrientations
{
    //Here check class name and then return type of orientation
    return UIInterfaceOrientationMaskPortrait;
}
@end

After that I implemented PortraitViewController.h as a base class

#import <UIKit/UIKit.h>
#import "PortraitViewController.h"
@interface Login : PortraitViewController
@end

It does not work at all, still allows view controller to rotate in landscape mode.

Is there any other solution i am using iOS 8 & don't want viewcontroller to rotate in landscape mode?

EDIT: Is it possible to have Landscape orientation only for some view controllers, and force other view controllers orientation to stick to Portrait?

SwiftArchitect
  • 47,376
  • 28
  • 140
  • 179
TechChain
  • 8,404
  • 29
  • 103
  • 228
  • where have you written first two lines? – iAnurag Aug 01 '15 at 06:04
  • In ViewDidLoad@iAnurag – TechChain Aug 01 '15 at 06:18
  • 1
    @JulianM posted the correct answer. You are, however, taking some risks with the coherence of your application, since the hidden view controllers will not receive orientation changes messages. You should consider redesigning your interface and fine tune your user experience, – SwiftArchitect Aug 03 '15 at 20:58
  • Possible duplicate of http://stackoverflow.com/questions/6064900/how-do-i-force-a-specific-uiinterfaceorientation-on-an-individual-view-in-a-uina – SwiftArchitect Aug 03 '15 at 21:03
  • @TechGuy did you still facing any problem – Anand Suthar Aug 07 '15 at 04:44
  • @Tech guy, Try this once.. In your appdelegates `- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window` method, check your controller and set the desired orientation. Also make sure you have the controller orientation methods set correctly. – iPP Aug 10 '15 at 06:51

9 Answers9

6

Try to subclass the UINavigationController you are using because the default UINavigationController is not forwarding the shouldAutorotate method to you viewcontroller.

Implement the following method in your UINavigationController subclass

- (BOOL)shouldAutorotate
{
    return [self.visibleViewController shouldAutorotate];
}

Now the UINavigationController forwards the method call to its current visible UIViewController so you need to implement shouldAutorotate there individually to get your desired effect.

KlimczakM
  • 12,576
  • 11
  • 64
  • 83
JulianM
  • 2,540
  • 18
  • 13
5

Your PortraitViewController is ok and I don't know your Storyboard configuration. In your case important thing is you should embedded your target view controller in another new navigation controller, then set it's class to your PortraitViewController and present that navigation modally, like I have done in below image and it's working as expected.

enter image description here

If you want to show animation that will make presentation animation like push animation

Below is mine PortrateNavigation subClass of UINavigationController

PortrateNavigation.h

#import <UIKit/UIKit.h>

@interface PortrateNavigation : UINavigationController

@end

PortrateNavigation.m

#import "PortrateNavigation.h"

@implementation PortrateNavigation

- (void)viewDidLoad  {
    [super viewDidLoad];
}

- (BOOL)shouldAutorotate {
    return YES;
}

- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskPortrait;
}

@end
Community
  • 1
  • 1
Anand Suthar
  • 3,678
  • 2
  • 30
  • 52
5

Try adding this method along with shouldAutorotate and supportedInterfaceOrientations

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
    //Setting the orientation of the view.  I've set it to portrait here.
    return UIInterfaceOrientationPortrait;

}

Also you can use this [UIViewController attemptRotationToDeviceOrientation] So that it rotates to the desired new orientation

gcharita
  • 7,729
  • 3
  • 20
  • 37
iPP
  • 441
  • 1
  • 7
  • 12
3

Create a category on the UINavigationController and override supportedInterfaceOrientations

#import "UINavigationController+Orientation.h"

 @implementation UINavigationController (Orientation)

-(NSUInteger)supportedInterfaceOrientations
{
   return [self.topViewController supportedInterfaceOrientations];
}

-(BOOL)shouldAutorotate
 {
    return YES;
 }

@end  

When you Embedded UINavigationController, Containers don't ask their children whether to rotate or not

Crashalot
  • 33,605
  • 61
  • 269
  • 439
M.Alatrash
  • 1,270
  • 1
  • 12
  • 30
1

You have to do it manually. All view controllers, in those you do not want to rotate view, implement following method.

- (BOOL)shouldAutorotate
{
    return NO;
}
VRAwesome
  • 4,721
  • 5
  • 27
  • 52
1

Tr this in your view controller

- (BOOL)shouldAutorotate{
    return NO;
}

- (NSUInteger)supportedInterfaceOrientations{
    return UIInterfaceOrientationPortrait |
           UIInterfaceOrientationPortraitUpsideDown;
}

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation{
    return UIInterfaceOrientationPortrait;
}
elp
  • 8,021
  • 7
  • 61
  • 120
Raman soni
  • 86
  • 4
1

1) Make a bool variable in your AppDelegate.

2) Then copy & paste below code in AppDelegate.m (modify it as per your requirement)

-(NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window{NSLog(@"%d", [UIDevice currentDevice].orientation)

if (self.isLandscape == YES) //bool created in first step
{
    return  UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight;
}

return UIInterfaceOrientationMaskPortrait;
}

3) Now copy & paste below code in the viewWillAppear method of the view controller for which you want to force orientation.

[AppDelegate sharedAppDelegate].isLandscape = YES; //bool created in first step
 NSNumber *value1 = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeRight]; //change the orientation as per your requirement
[[UIDevice currentDevice] setValue:value1 forKey:@"orientation"];

4) Now before pushing this view controller, you need to set the bool first. So, let's say you want to push ABC view controller

[AppDelegate sharedAppDelegate].isLandscape = YES;
[self.navigationController pushViewController:<ABC view controller instance> animated:NO];

Hope this helps!!

Manish Verma
  • 539
  • 1
  • 4
  • 11
  • Shouldn't the return type of 'supportedInterfaceOrientationsForWindow:' be 'UIInterfaceOrientationMask' instead of 'NSUInteger'? – Charlie Scott-Skinner Sep 05 '16 at 09:18
  • @CharlieScott-Skinner Yes. You can write it there. But as the definition suggests 'typedef NS_OPTIONS(NSUInteger, UIInterfaceOrientationMask)' you can also type NSUInteger. – Manish Verma Sep 07 '16 at 09:21
0
class ViewController: UIViewController {
    override func shouldAutorotate() -> Bool {
        return false
    }
}

Here is the link to the topic: http://koreyhinton.com/blog/lock-screen-rotation-in-ios8.html

0

If you want to temporarily disable automatic rotation, avoid manipulating the orientation masks to do this. Instead, override the shouldAutorotate method on the initial view controller. This method is called before performing any autorotation. If it returns NO, then the rotation is suppressed.

So you need to subclass 'UINavigationController', implement shouldAutorotate and use your navigation controller class in your storyboard.

- (BOOL)shouldAutorotate

{

id currentViewController = self.topViewController;


 if ([currentViewController isKindOfClass:[DetailViewController class]])
    return NO;

return YES;

}

an alternate approach can be found on

http://www.sebastianborggrewe.de/only-make-one-single-view-controller-rotate/