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, b
- (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!
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; } }
-(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:
.
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...
... 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;
}