Set different supportedInterfaceOrientations for different UIViewControllers - objective-c

So, as by the question, I use the following code to set userinterfaceOrientation for the viewcontroller.
- (BOOL) shouldAutorotate
{
return YES;
}
-(NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait;
}
I tried setting UIInterfaceOrientationMaskAll for another viewController.
Prior, I checked all the items for Supported interface orientations in the info-plist. Both the viewControllers returned true(as set in the info-plist) for all the orientations and didn't obey the above code. IT worked even in the absence of the above code. Is there anyway to restrict certain Supported interface orientations for particular classes? I made it working for the pre - iOS6 versions by following this link.

I was able to accomplish this by placing my supported orientation logic in a custom UINavigationController. I then segue to the relevant view controller.
#implementation PortraitNavigationController
- (NSUInteger)supportedInterfaceOrientations{
return UIInterfaceOrientationMaskPortrait;
}
...

I'd say implement your shouldAutorotateToInterfaceOrientation: on every view controller to make it return only YES for those orientations you wish to support.

Related

upSideDown iPhone orientation is not working in iOS 6?

hope you will be fine and doing your best.
I am getting a problem in upSideDown Orientation in my iOS 6, while I think I am doing everything perfect, but I don't know why it is not working for me. I am sharing my problem with you so to get any solutions.
What I have done so far:
a) In xcode project Summary tab, I have enabled all the 4 orientations.
b) I have added piece of code (written below) in all of my controller classes.
-(BOOL)shouldAutorotate
{
return YES;
}
-(NSInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskAll;
}
but still the upSideDown Orientation is not working
Thanks in anticipation.
I have found its solution.
We need to make a separate class of UINavigation Controller type. In .m file add the following methods
// Deprecated in iOS6, still needed for iOS5 support.
// ---
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
// return (interfaceOrientation == UIInterfaceOrientationPortrait);
return YES;
}
// iOS6 support
// ---
- (BOOL)shouldAutorotate
{
return YES;
}
-(NSUInteger)supportedInterfaceOrientations{
return UIInterfaceOrientationMaskAll;
}
Now assign this newly created class to your Navigation Controller in story board. Also add the .m file of this class in 'Project -> Build Setting -> Compile Sources'. Run the project and it will support and perform all the orientations including upSideDown.
I hope it will help you all.
Regards

iOS 6 UIInterfacePortrait ONLY viewcontroller being presented & stuck in landscape... when coming back from a landscape viewcontroller in nav stack

So like many others, I ran into the problem of only having one or two viewcontrollers support both portrait and landscape interface orientations, in an otherwise portrait only app. Everything worked fine prior to iOS 6, but suddenly autorotating stopped working. Thanks to some great questions here, I was able to resolve that issue by having the initial navController return the individual topViewController's preference for shouldAutorotate via:
- (BOOL)shouldAutorotate
{
return self.topViewController.shouldAutorotate;
}
-(NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskAll;
}
However, I have stumbled onto a new problem. the root vc (viewController A) should NOT autorotate and should only support portrait. ViewController B in the nav stack supports portrait and landscape. If I am in viewController B, and am in landscape, and touch "back" to pop the view back to viewController A... vc A loads in landscape, which it is not supposed to even support, and wont rotate back to portrait because shouldAutorotate for vc A is set to NO...
Any ideas on how to deal with this would be greatly appreciated. My initial thought was to override vc B's "back" button with a manual method that first force rotates back to portrait if the view is in landscape... then pops the viewcontroller back to vc A... but I cant figure out how to force a rotation programatically. Any ideas?
here are the interface methods in vc A:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return NO;
}
-(BOOL)shouldAutorotate
{
return NO;
}
-(NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationPortrait;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
return UIInterfaceOrientationPortrait;
}
and here is what they are in vc B:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
-(BOOL)shouldAutorotate
{
return YES;
}
-(NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskAllButUpsideDown;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
return UIInterfaceOrientationPortrait;
}
In vcA set
-(BOOL)shouldAutorotate
{
return YES;
}
But keep
-(NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationPortrait;
}
Then the view will rotate back to the (only) supported orientation when you return from vcB
The problem is that all container view controllers (Tab Bar Controller, Navigation Controller etc.) support all those interface orientations that you give in your plist file. When the system asks for the supported interface orientations the root view controller's settings and method implementations override it's children's.
In this case the Navigation Controller supports both landscape and portrait and when the B View controller pops, although the system asks for A's interface orientations, it will ask it's root view controller too and that will be the "winner" and since the Navigation Controller supports landscape, it stays in landscape despite that A supports portrait only.
One solution is, that you subclass the root view controller and change it's rotation methods dynamically as needed. When only portait is needed your root's implementation should return portait only and when both orientations are available, then your root should return both.

Supporting different orientations in iOS 6.0 for different view controllers

I am having custom split view controller in my App with a master controller and a detailed controller.
- (id)initWithMasterController:(UIViewController*)aMasterController
detailedController:(UIViewController*)aDetailedController;
The controllers provided for the master controller and details controller are UINavigationController.
As part of my app, there are two possible cases for orientation handling:
When six combination of controllers are used in master and details controller, all the orientations are supported for the app.
When there is a StudentDetailsViewController at the details controller alone, only two possible orientations can be supported. (Landscape)
When ever the device's orientation is changed, the below things happen in versions below iOS 6.0
The -shouldAutorotateToInterfaceOrientation: method gets called. The implementation of that method is below: At run time, I forward the request to master controller and details controller with the same call.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
BOOL res = [masterController shouldAutorotateToInterfaceOrientation:interfaceOrientation]
&& [detailedController shouldAutorotateToInterfaceOrientation:interfaceOrientation];
return res;
}
The masterController's -shouldAutorotateToInterfaceOrientation will return TRUE. The implementation of the method in StudentViewController is below.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (IS_IPAD) ? UIInterfaceOrientationIsLandscape(interfaceOrientation)
: UIInterfaceOrientationIsPortrait(interfaceOrientation);
}
The ability to get information on the new orientation to be changed helps me to decide if rotation should be enabled or not.
With iOS 6.0:
When ever the device's orientation is changed, the below things happen in versions of iOS 6.0
The method -shouldAutorotate of the split view controller gets called. Its implementation is below
- (BOOL)shouldAutorotate {
BOOL res = [masterController shouldAutorotate]
&& [detailedController shouldAutorotate];
return res;
}
The detailedController's shouldAutorotate calls the navigationController. The implementation of autorotate feature in StudentsController:
- (BOOL)shouldAutorotate {
return YES;
}
- (NSUInteger)supportedInterfaceOrientations {
return (UIInterfaceOrientationMaskLandscapeLeft
| UIInterfaceOrientationMaskLandscapeRight);
}
But with iOS 6.0, I am unable to control the orientation. Even though the supportedInterfaceOrientations method gets called, when the shouldAutorotate method of the StudentsDetailsController gets called, from the detailsController's shouldAutorotatemethod, the shouldAutorotateMethod does not obey the options mentioned in the supportedInterfaceOrientations method.
UPDATE:
I read the docs and the below notes are provided in the document.
sometimes you may want to dynamically disable automatic rotation. For
example, you might do this when you want to suppress rotation
completely for a short period of time. You must temporarily disable
orientation changes you want to manually control the position of the
status bar (such as when you call the
setStatusBarOrientation:animated: method).
If you want to temporarily disable automatic rotation, avoid
manipulating the orientation masks to do this. Instead, override the
shouldAutorotate method on the topmost view controller. This method is
called before performing any autorotation. If it returns NO, then the
rotation is suppressed.
Is it possible to temporarily disable automatic rotation based on the current orientation?
I believe this is some type of issue in iOS where the rootViewController does not consult the childViewController for their preferred orientation. However, you should try something like the following :
if (self.interfaceOrientation != UIInterfaceOrientationPortrait)
{
[[UIDevice currentDevice] performSelector:NSSelectorFromString(#"setOrientation:") withObject:(id)UIInterfaceOrientationPortrait];
}
to change the orientation back to portrait for a given view.
In your application delegate class define the following method, this method gets called before any other rotation methods in application.
Create a flag(isRotationEnabled) which will decide orientation of your app.
- (NSUInteger) application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
return self.isRotationEnabled ?
UIInterfaceOrientationMaskAll :
UIInterfaceOrientationMaskPortrait;
}
Change this flag based on different conditions in you app using the following code
MyAppDelegate *appDelegate = (MyAppDelegate *)[[UIApplication sharedApplication] delegate];
appDelegate.isRotationEnabled = NO;

Device Orientation in iOS 6.0 UINavigationController

I have a UINavigationController in UITabbarcontroller. I want to rotate only one view cotnroller inside UINavigationController.
Here is the code snippet I am using.
-(NSUInteger)supportedInterfaceOrientations
{
if (CURRENTDEVICE == IPHONE)
return [self.navigationController supportedInterfaceOrientations] | UIInterfaceOrientationMaskAllButUpsideDown;
else
return UIInterfaceOrientationMaskAll;
}
-(BOOL)shouldAutorotate {
return YES;
}
I have a category on UINavigationController as well:
#import "UINavigationController+autorotate.h"
#implementation UINavigationController (autorotate)
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskAllButUpsideDown;
}
#end
I am not sure how to implement it.
you can hard code it with cgrect. here is a link to another question that might help you. there is a nice example of hard coding two different views for rotation in there, but i don't recomend it personally. anyhow i thought that might point you to the right direction.
https://stackoverflow.com/questions/12867792/ios-rotation-causing-views-to-displace-shift-forcing-me-to-use-non-sensical-har
there is a set of codes in that question that might get you started. you also have an option in starboard( if you are using storyboard) to set rotations in IB which is much easier.
hope this helps
adrian
In your category in the supportedInterfaceOrientations implementation, you could check for the topViewController. You can use kindOfClass: method to work out which class it is... Then return a different orientation from the default of your navigation.
You could also subclass UINavigationController, and do this check the same way. Subclassing the navigation controller isn't recommended until, iOS 6, the documentation still states this but Apple engineers have told me that with the new rotation logic, you can subclass the UINavigationController.

Force iOS app to launch in landscape mode

I am developing an app for iOS 5, which have to run in landscape mode. My problem is that I cannot get it to flip initially.
I have tried the adding "Initial interface orientation" set to "Landscape (right home button)"
and adding the following method to my view controller:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationLandscapeRight);
}
I can wrap my head around how it is supposed to work. (I found the code here)
I am also wondering how to use the "Supported Device Orientation" available in the Xcode 4.2 project setup, it does not seem to do anything.
I have been looking around the website and have not been able to find an example that solves my problem.
Thank you.
In your application’s Info.plist file, add the UIInterfaceOrientation
key and set its value to the
landscape mode. For landscape
orientations, you can set the value
of this key to
UIInterfaceOrientationLandscapeLeft
or
UIInterfaceOrientationLandscapeRight.
Lay out your views in landscape mode and make sure that their autoresizing options are set correctly.
Override your view controller’s shouldAutorotateToInterfaceOrientation: method and return YES only for the
desired landscape orientation and NO
for portrait orientations.
use the following in appDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight];
also set the required orientations in
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationLandscapeRight);
}
//Here are some iOS6 apis, used to handle orientations.
- (BOOL)shouldAutorotate NS_AVAILABLE_IOS(6_0)
- (NSUInteger)supportedInterfaceOrientations - (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
When you click on your project's name in XCode and select your target under TARGETS, under Summary tab there's a visual representation of the supported device orientation settings. That was how I managed to do it.
i think if you at the supported interface orientations in the project plist it will work. just add a new line called "Supported interface orientations" and make it of array type and add 2 items for each of teh landsape views u want. havent tested this just a quick guess
Try this this will help you, write this code in you viewdidload.
[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight];