iOS Rotate View Only One View Controller's View - iphone

I have two view controllers in a single project. However, I want one of the view controller's to autorotate, and the other to not.
If I set the master project setting as seen below:
Then, all view controllers autorotate, regardless of the following code in the view controller I do NOT want to autorotate:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
if (interfaceOrientation == UIInterfaceOrientationPortrait) {
return YES;
}
return NO;
}
However, if I set the master project settings as seen below, the view controller that I do not want to autorotate does not, but that also means neither can the one that I DO want to.
How must I integrate the master project (plist file) settings with those of the view controllers so that one view controller will auto-rotate while the other will not?

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
was depreciated in iOS 6 so if that's what your project is running, that's why it's not working. What you need to do is implement:
- (NSUInteger)supportedInterfaceOrientations
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
The first one will tell the controller what orientation(s) it is allowed to use, and the second will tell it which one to use first. Note that the first method is only called if the method shouldAutorotate: returns YES.
These are the constants you can use for supportedInterfaceOrientations:
UIInterfaceOrientationMaskPortrait
UIInterfaceOrientationMaskLandscapeLeft
UIInterfaceOrientationMaskLandscapeRight
UIInterfaceOrientationMaskPortraitUpsideDown
UIInterfaceOrientationMaskLandscape
UIInterfaceOrientationMaskAll
UIInterfaceOrientationMaskAllButUpsideDown
Note that these only work on iOS 6.0.

Assume I am using tabbarController & iOS<6.0 try to use the following code solve your issue:
//In First View Controller
//BOOL activeStatus;
-(void)viewWillAppear:(BOOL)animated
{
activeStatus=YES;
}
-(void)viewWillDisappear:(BOOL)animated
{
activeStatus=NO;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
if ((interfaceOrientation == UIInterfaceOrientationLandscapeLeft || interfaceOrientation == UIInterfaceOrientationLandscapeRight) && activeStatus==YES)
{
return YES;
}
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
//In Second View Controller
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}

Related

Keep all views portrait except one

Right I have done a lot of research on this and have hit a block.
I am developing an app which has multiple view controllers. I have the 'homepage', if you will, which all the others views can be access from (this ViewController.m). I also then have a UINavigationController.m attached to the ViewController.m to allow a full navigation bar etc.
My problem is that I am wanting all views to be shown in portrait EXCEPT one view, which I only want in landscape. In my app options, I have set it to enable all orientations and then I was reading that you should override the main orientation in your root view controller (which I assume is the navigation controller?), so I add:
- (BOOL)shouldAutorotate {
return YES;
}
- (NSUInteger)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskPortrait;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
This overrides everything and only portrait works. I have then tried adding:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return (interfaceOrientation == UIInterfaceOrientationLandscapeLeft);
}
- (NSUInteger)supportedInterfaceOrientations{
return UIInterfaceOrientationMaskLandscape;
}
To the view that I want to have in landscape only but it fails to work in the simulator.
Can anyone provide me with a solution? :/
(I would like iOS5 and iOS6 support if possible)
[EDIT]
I should add, I haven't edited AppDelegate in any way.

how to enable rotation only on video

I've been looking for the past days a solution to enable rotation ONLY when MPMoviePlayerViewController is triggered, without any luck.
I tried to enable the app to all rotations, and disabling it at each view, but it didn't work either.
does any one have an idea?
In target settings, enable all orientations
(optional, UIViewController default is portrait only) In all the other view controllers, do the following:
// Deprecated in iOS 6, but still needed for earlier versions of iOS:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
// For iOS 6 and up
- (NSUInteger)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskPortrait;
}
In the one view controller that should rotate, do the following:
// Deprecated in iOS 6, but still needed for earlier versions of iOS:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return YES;
}
// For iOS 6 and up
- (NSUInteger)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskAll;
}
This is assuming the rotating view controller will not be inside the same container view controller (such as UINavigationController or UITabBarController) as the non-rotating view controllers.
Create a new ViewController for the player Full screen and add:
- (BOOL)shouldAutorotateToInterfaceOrientation: (UIInterfaceOrientation)interfaceOrientation {
return (interfaceOrientation == UIInterfaceOrientationLandscapeRight);
}
to your code.
Make sure you present the ViewController.
(supporting iOS 6 and above)

I want to restrict some of the view controller to landscape in ios6

I'm trying to restrict one view controller which on top of UINavigationController. To do that i've created a UINavigationController subclass and implemented 2 methods
- (BOOL)shouldAutorotate {
return [[self.viewControllers lastObject] shouldAutorotate];}
- (NSUInteger)supportedInterfaceOrientations {
return [[self.viewControllers lastObject] supportedInterfaceOrientations];}
I want the first viewcontroller on top of UINavigationController(which is Root View Controller) should be in portrait mode and the next view controller which i'm pushing from the root view controller should be Landscape mode(ONLY).
So i'm overriding those two methods in both view controllers.
In the root view controller
- (BOOL)shouldAutorotate {
return NO;}
- (NSUInteger)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskPortrait;}
In the next view controller
- (BOOL)shouldAutorotate {
return YES;}
- (NSUInteger)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskLandscape;}
Its working fine but not completely. For the first time when I push the view controller its showing in portrait mode(Not restricting to landscape as I expected) and once I rotate the device/simulator and its working fine and restricting to landscape only.
Can anyone help in this?
Try this out.
Call this one in the viewWillAppear will explicitly tell the device to jump to the portrait orientation.
[[UIDevice currentDevice] performSelector:NSSelectorFromString(#"setOrientation:") withObject:(id)UIInterfaceOrientationPortrait];
I don't think this is the right solution. But if you got no other options, you can use this.
Happy Coding :)
U present new controller :
SecondViewController *objSecondViewController = [[SecondViewController alloc]initWithNibName:#"SecondViewController" bundle:nil];
[self.navigationController presentViewController:objSecondViewController animated:NO completion:^{}];
In new controller :
- (BOOL)shouldAutorotate {
return YES;
}
- (NSUInteger)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskLandscape;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return UIInterfaceOrientationLandscapeLeft;
}
This worked for me. Just try using this :
1) YourApp-Info.plist
Add one more array for Supported interface orientations
Add your required orientation to this dictionary
Refer below screenshot :
2) Project Target
Select the required orientation from Supported Interface Orientations
Refer below screenshot :
UIViewController have the following function. You can implement this in your view controller where you want to restict portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations
if(interfaceOrientation == UIInterfaceOrientationPortrait)
return YES;
else
return NO;
}

IOS6 rotation issue

I know you have to use the new rotation methods for IOS6, but it seems the method I've written doesn't work.
I setted my plist file to allow all rotation but not portraitUpsideDown
I then had the following in my appDelegate:
self.navController = [[UINavigationController alloc] initWithRootViewController:self.viewController];
[self.window setRootViewController:navController]; //add nav controller to be the root view
Then in my rootView, to push to another controller, I have:
WebViewViewController *webController = [[JBWebViewViewController alloc] init];
webController.urlString = urlName;
[self.navigationController pushViewController:webController animated:YES];
And In the web controller I have:
#pragma mark - System Rotation Methods
//for any version before 6.0
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
//only allow landscape
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
/for 6.0+
- (BOOL)shouldAutorotate{
return NO;
}
- (NSUInteger)supportedInterfaceOrientations{
return UIInterfaceOrientationMaskPortrait;
}
What I want do, is to allow 3 rotations in the root view, but when switch to the web view(note I do push navigation, not add subview), I only want to allow portrait view.
Someone help me please
-------UPDATE----------
I've created my own navController subclass of UINavigationController, I have an BOOL landscapeModeOn that I can setup to tell auto rotation specs
#pragma mark - System Rotation Methods
//for any version before 6.0
- (BOOL)shouldAutorotateToInterfaceOrientation (UIInterfaceOrientation)interfaceOrientation
{
if (landscapeModeOn) {
return interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown;
} else {
return interfaceOrientation == UIInterfaceOrientationPortrait;
}
}
//for 6.0+
- (NSUInteger)supportedInterfaceOrientations{
if (landscapeModeOn) {
return UIInterfaceOrientationMaskAllButUpsideDown;
} else {
return UIInterfaceOrientationMaskPortrait;
}
}
- (BOOL)shouldAutorotate{
UIInterfaceOrientation ori = [UIDevice currentDevice].orientation;
if (landscapeModeOn) {
return ori != UIInterfaceOrientationPortraitUpsideDown;
} else {
return ori == UIInterfaceOrientationPortrait;
}
}
IN the subviews loading, I do:
- (void)viewWillAppear:(BOOL)animated{
//get nav controller and turn off landscape mode
JBNavController *navController = (JBNavController*)self.navigationController;
[navController setLandscapeModeOn:NO];
[navController shouldAutorotate];
}
--------------------Refer to best answer's quote
For IOS6, apple is now focusing on using the Storyboard's AutoLayout together with the new rotation definitions, it is difficult to fix some tiny bugs for IOS6 based on the ios 4.3 and ios 5 coding structure
From applefreak, his suggestion hinted on:
A main challenge in your case is not handling the orientations. Actually it's locking the different view controllers to particular orientation
Although manual rotate view seems really hard to do without any bugs, but it seems the only solution I am now trying, will post more once solved
For your situation you will have to subclass your NavigationController and add the shouldAutorotate and supportedInterfaceOrientations methods to it. iOS6 now asks your navigation stack in the reverse order to iOS5 so it will ask your NavigationController first and if that returns YES it won't even consult with it's child view controllers. To fix that you have to add the logic yourself to do this
So in your subclassed navigation controller you manually ask your current viewcontroller it's autorotation abilities:
- (BOOL)shouldAutorotate
{
return self.topViewController.shouldAutorotate;
}
- (NSUInteger)supportedInterfaceOrientations
{
return self.topViewController.supportedInterfaceOrientations;
}
and in your individual viewcontrollers you can now implement those functions and have them return the values you want which you have defined in your question.
I hope this makes sense.
Following code is wrong!
- (BOOL)shouldAutorotate{
return NO;
}
- (NSUInteger)supportedInterfaceOrientations{
return UIInterfaceOrientationMaskPortrait;
}
Remember that supportedInterfaceOrientations gets called only if shouldAutoRotate returns YES. Now root view controllers decides whether it's children rotates or not.
In your case I would suggest to have a base class controller to your self.viewController and set self.viewController to root view controller not navigationController otherwise rotation methods won't be invoked! I ran into this same issue. You should have a HAS-A relationship with base view controller and it's children. Return Yes/No from ShouldAutoRotate based on active children and same for supported orientation. If you follow this architecture then it would be consistent for complex App.
For example in your case BaseviewController should return YES from shouldAutoRotate and returns UIInterfaceOrientationPortrait from supported orientation delegate when webviewController is active. I hope this makes sense.
It common code for iOS5 and iOS6
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation duration:(NSTimeInterval)duration
{
if (UIInterfaceOrientationIsLandscape(interfaceOrientation))
{
// here to implement landscope code
}
else
{
// here to implement setframePortrait
}
}

Autorotation lock, programmatically

Does anybody know if there is a possibility to lock autorotation of iPhone programmatically for just one view?
I want to make some kind of help with semi-transculent view, but I want to support only landscape orientation even all other views can rotate.
So I wish to lock rotation when this view is on the top.
tnx
EDIT: More details: one UIController has 7 UIView...and I wish to lock the autorotation just when the last one occurs on the top.
This question was asked over a year ago but the accepted method is now deprecated in iOS 6 so if anybody is interested in doing this in iOS 6 then you need to use supportedInterfaceOrientations on the topmost controller.
Imagine you have a setup like this...
Tab Bar Controller
Navigation Controller
View Controller
... then you need to set the supportedInterfaceOrientations method on the tab bar controller.
Create a subclass of the tab bar controller (or navigation controller if that is at the top) and set these methods in it...
- (BOOL)shouldAutorotate {
//Use this if your root controller is a navigation controller
return self.visibleViewController.shouldAutorotate;
//Use this if your root controller is a tab bar controller
return self.selectedViewController.shouldAutorotate;
}
- (NSUInteger)supportedInterfaceOrientations {
//Navigation Controller
return self.visibleViewController.supportedInterfaceOrientations;
//Tab Bar Controller
return self.selectedViewController.supportedInterfaceOrientations;
}
... then in your individual view controllers you can set the properties you want...
- (BOOL)shouldAutorotate {
return YES;
}
- (NSUInteger)supportedInterfaceOrientations{
//return supported orientation masks
return UIInterfaceOrientationMaskLandscape;
}
Use the following...
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return (interfaceOrientation == UIInterfaceOrientationLandscapeLeft) || (interfaceOrientation == UIInterfaceOrientationLandscapeRight);
}
You can attach it to the window. After the view is loaded, do
[self.view.window addSubview:yourStaticView];
[self.view.window bringSubviewToFront:yourStaticView]; // Do only if necessary
Remove it when leaving this view. Probably in viewWillDisappear: or viewDidDisappear:.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
{
//If you don't want to support multiple orientations uncomment the line below
return (toInterfaceOrientation == UIInterfaceOrientationPortrait);
//return [super shouldAutorotateToInterfaceOrientation:toInterfaceOrientation];
}
i feel there are many specific answers that work intermittently, but none provide insight as to what the ramifications or side effects are, in respect to the rest of the app or other view controllers, if the user starts tilting the phone outside of the view controller you want to control the orientation for...
after playing around with it, you may realize (like myself) that adverse or undesired results may occur (ie. orientation changes occur when you don't want them to, or vice versa).
my main realization involved that only the 'root view controller' will invoke 'shouldAutorotate', and NOT just any individual view controller you attempt to override with.
with this realization it seemed quite difficult to 'lock' a specific orientation for a specific view controller.
(meaning have vc_A always be portrait and not allowed to change to landscape, while having vc_B always be landscape and not allowed to change to portrait)
after acknowledging this, the following algorithm is what worked for me in being able to only rotate on specified view controllers.
setup:
first you have to allow the orientations you desire, in either the info.plist or the main project settings file (these orientations will be the only ones you can use in your code)
code:
1) in my root view controller (here: MasterViewController) i designated a BOOL property (allowAutorotate) that will be utilized when 'shouldAutorotate' is invoked.
2) also make the root view controller a singleton so its easily accessible from any other child view controller (without having to pass around references).
note: you may also use the observer/notification pattern or delegation or some other pattern, but for me the singleton pattern was easiest
3) add the delegate '-(BOOL)shouldAutorotate' and utilize the BOOL allowAutorotate for its return
4) create an instance method 'setInterfaceOrientation'. some other class will call this method in their 'viewDidLoad' and/or in their 'viewWillDisappear'
// 1)
#implementation MasterViewController {
BOOL allowAutorotate;
}
// 2)
+ (id)sharedMasterViewController {
static MasterViewController *sharedMasterViewController = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedMasterViewController = [[self alloc] init];
});
return sharedMasterViewController;
}
- (id)init
{
self = [super init];
if (self)
{
allowAutorotate = NO;
}
return self;
}
// 3)
- (BOOL)shouldAutorotate
{
return allowAutorotate;
}
// 4)
- (void)setInterfaceOrientation:(NSInteger)orientation
{
allowAutorotate = YES;
NSNumber *value = [NSNumber numberWithInt:orientation];
[[UIDevice currentDevice] setValue:value forKey:#"orientation"];
allowAutorotate = NO;
}
5) finally in some other class get the root view controller and invoke 'setInterfaceOrientation' accordingly
// 5)
#import "MasterViewController.h"
#implementation SomeViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
[[MasterViewController sharedMasterViewController] setInterfaceOrientation:UIInterfaceOrientationLandscapeRight];
}
- (void)viewWillDisappear:(BOOL)animated
{
[[MasterViewController sharedMasterViewController] setInterfaceOrientation:UIDeviceOrientationPortrait];
}
notes:
1) the result of this example should be that the app will initially load in portrait, then when you load 'SomeViewController', it will change to landscape, and then when you remove it, it will change back to portrait.
2) it works like this...
every time you physically tilt the phone, the delegate 'shouldAutorotate' is invoked (only from the 'root view controller'),
as well every time you programmatically tilt the phone
NSNumber *value = [NSNumber numberWithInt:orientation];
[[UIDevice currentDevice] setValue:value forKey:#"orientation"];
the delegate 'shouldAutorotate' is invoked.
this is why we first 'allowAutorotate = YES;', then 'tilt the phone', then 'allowAutorotate = NO;'
hence, we have a result of only allowing/performing the orientation change once, programmatically, exactly when we want to.
glhf!
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { 
return (interfaceOrientation == UIInterfaceOrientationLandscapeLeft) || (interfaceOrientation == UIInterfaceOrientationLandscapeRight);
}
I have found very simple and working solution. By adding the top view I set a BOOL which then controls rotating.
// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations; we support all.
if (helpViewOnTheTop) {
return (interfaceOrientation == UIInterfaceOrientationLandscapeLeft) || (interfaceOrientation == UIInterfaceOrientationLandscapeRight);
}
else
{
return YES;
}
}