IOS view controller orientation - ios

I have parent view controller and another modal view controller.
I presented modal view controller within parent's context:
readingViewController * reading_view_controller = [[readingViewController alloc] initWithNibName:#"readingViewController" bundle:nil];
[self setModalPresentationStyle:UIModalPresentationCurrentContext];
[self presentModalViewController:reading_view_controller animated:YES];
Parent viewController will not orient Landscape; so, i added these methods in the parent viewController:
- (NSUInteger)supportedInterfaceOrientations{
return UIInterfaceOrientationMaskPortraitUpsideDown|UIInterfaceOrientationMaskPortrait;
}
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation{
return (toInterfaceOrientation == UIInterfaceOrientationPortrait || toInterfaceOrientation == UIInterfaceOrientationPortraitUpsideDown);
}
The presented viewController (modally presented) should orient to all possible orientations; so, i added these methods:
- (NSUInteger)supportedInterfaceOrientations{
return UIInterfaceOrientationMaskAll;
}
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation{
return YES;
}
But, because I assumed (UIModalPresentationCurrentContext), the presented viewController doesn't orient in IOS 6.0 while it is working as expected in IOS 5.0
How to solve this problem please?

If you have a tab-based app, then first add some code in app delegate and also self.window.rootviewcontroller-self.tabbarcontroller.
#implementation UITabBarController (SK8FASTR2App)
-(BOOL)shouldAutorotate
{
return YES;
}
- (NSUInteger)supportedInterfaceOrientations
{
// your custom logic for rotation of selected tab
if (self.selectedIndex==3){
return UIInterfaceOrientationMaskPortrait;
}
else {
UIInterfaceOrientationMaskPortrait|UIInterfaceOrientationMaskPortraitUpsideDown|UIInterfaceOrientationLandscapeLeft|UIInterfaceOrientationLandscapeRight;
return UIInterfaceOrientationMaskAll;
}
}
#end
before
#implementation AppDelegate
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
return UIInterfaceOrientationMaskAll;
}
Change orientation on that class
-(BOOL)shouldAutorotate
{
return NO;
}
-(NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskLandscapeRight;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return UIInterfaceOrientationLandscapeRight;
}

You should implement
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation;
eg :-
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return UIInterfaceOrientationMaskAll;
}

Related

Disable UITableViewcontroller from rotating in Landscape (keep it Portrait)

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;
}

Orientation doesn't change after Pushing (push segue) a View on the UINavigationViewController

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)

iOS 7. Change page orientation only for one view controller

I have iPhone application that supports only Portrait orientation. I want to add to my project view controller that will support only Landscape orientation? Is it possible? If yes how could I achieve that?
I have tried to crate category file like this:
#implementation UINavigationController (Rotation_IOS7)
-(BOOL)shouldAutorotate
{
return YES;
}
-(NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskLandscape;
}
If I do this I get this error:
Terminating app due to uncaught exception UIApplicationInvalidInterfaceOrientation, reason: Supported orientations has no common orientation with the application, and shouldAutorotate is returning YES
I've tried this and it works: http://www.sebastianborggrewe.de/only-make-one-single-view-controller-rotate/
First, add these code to your AppDelegat class.
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
// Get topmost/visible view controller
UIViewController *currentViewController = [self topViewController];
// Check whether it implements a dummy methods called canRotate
if ([currentViewController respondsToSelector:#selector(canRotate)]) {
// Unlock landscape view orientations for this view controller
return UIInterfaceOrientationMaskAllButUpsideDown;
}
// Only allow portrait (standard behaviour)
return UIInterfaceOrientationMaskPortrait;
}
- (UIViewController*)topViewController {
return [self topViewControllerWithRootViewController:[UIApplication sharedApplication].keyWindow.rootViewController];
}
- (UIViewController*)topViewControllerWithRootViewController:(UIViewController*)rootViewController {
if ([rootViewController isKindOfClass:[UITabBarController class]]) {
UITabBarController* tabBarController = (UITabBarController*)rootViewController;
return [self topViewControllerWithRootViewController:tabBarController.selectedViewController];
} else if ([rootViewController isKindOfClass:[UINavigationController class]]) {
UINavigationController* navigationController = (UINavigationController*)rootViewController;
return [self topViewControllerWithRootViewController:navigationController.visibleViewController];
} else if (rootViewController.presentedViewController) {
UIViewController* presentedViewController = rootViewController.presentedViewController;
return [self topViewControllerWithRootViewController:presentedViewController];
} else {
return rootViewController;
}
}
Then, in your landscape view controller, add this method
- (void)canRotate { }
I have search through numerous topics and finally found a working solution.
In my example, I have two VC's:
A -> VC that is embedded inside Nav. Controller and should only support Portrait view.
B -> VC that is not embedded inside a VC and should support Landscape only.
I would like to go from view A to view B (by pressing a button) and back to view then A with the specific orientations still correct.
I. Create a Category for UINavigationController and write the following in its .m file: (the code will be automatically called)
- (NSUInteger)supportedInterfaceOrientations
{
NSLog(#"supportedInterfaceOrientations = %d ", [self.topViewController supportedInterfaceOrientations]);
return [self.topViewController supportedInterfaceOrientations];
}
- (BOOL)shouldAutorotate
{
return self.topViewController.shouldAutorotate;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// You do not need this method if you are not supporting earlier iOS Versions
return [self.topViewController shouldAutorotateToInterfaceOrientation:interfaceOrientation];
}
II.
Create a modal segue between A and B and after that between another one between B and A.
III. Write down in each of the View Controllers .m files the following:
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskLandscape;
}
OR
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait;
}
After adding this code. You will be able to change orientation for the single view B.
Edit:
create a category in .h and then implement those methods
use these methods in the view controller where you want to support landscape
#implementation UINavigationController (Rotation_IOS7)
-(BOOL)shouldAutorotate
{
return YES;
}
-(NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskLandscape;
}

1st ViewController in Portrait and SecondViewController in Landscape Mode

My requirement is this my 1st viewcontroller open in Portrait mode only.and when user goes to 2nd viewcontroller i want that controller in Landscape mode how may i do this
i tried this code
1st ViewController.m
- (BOOL)shouldAutorotate
{
returnc YES;
}
-(NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
return UIInterfaceOrientationMaskPortrait;
}
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interface
{
return (interface==UIInterfaceOrientationMaskPortrait);
}
Code for 2nd ViewController.m
- (BOOL)shouldAutorotate
{
return YES;
}
-(NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskLandscapeRight | UIInterfaceOrientationMaskLandscapeLeft;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return UIInterfaceOrientationLandscapeRight;
//return UIInterfaceOrientationMaskLandscape;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationLandscapeRight || interfaceOrientation == UIInterfaceOrientationLandscapeLeft);
}
this will not working fine for me.
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
return UIInterfaceOrientationIsPortrait(toInterfaceOrientation);
}
UPDATED:
You can do this by creating category of UINaviagationController
code for .h file is
#interface UINavigationController (autorotation)
-(BOOL)shouldAutorotate;
-(NSUInteger)supportedInterfaceOrientations;
and code for .m file is
#implementation UINavigationController (autorotation)
-(BOOL)shouldAutorotate
{
UIInterfaceOrientation interfaceOrientation = [UIApplication sharedApplication].statusBarOrientation;
[self.topViewController shouldAutorotate];
return YES;
}
-(NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskAll;
}
#end
paste following code in viewcontroller .m file of second view controller (under #implementation section)
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationLandscapeRight || interfaceOrientation == UIInterfaceOrientationLandscapeLeft);
}
Now select the second view controller in storyboard (Selection indicated by blue border around view controller), go to the attribute inspector (right side 'shield' like image) change the orientation to landscape.. That's it.. .Tell me if it doesn't work for u. ..:)
I am solving my problem using Category....
Add new files and select Category and make subclass UINavigationController class.
here is the code for category for .h
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
#interface UINavigationController (orientation)
#end
code for .m file
#import "UINavigationController+orientation.h"
#implementation UINavigationController (orientation)
- (BOOL)shouldAutorotate
{
return YES;
}
- (NSUInteger)supportedInterfaceOrientations
{
AppDelegate * delegate=(AppDelegate *)[[UIApplication sharedApplication]delegate];
if (delegate.islandscape)
{
// for iPhone, you could also return UIInterfaceOrientationMaskAllButUpsideDown
return UIInterfaceOrientationMaskLandscape;
}
return UIInterfaceOrientationMaskPortrait;
}
#end
isLandscape is declared in App delegate to check weather First view controller or secondView Controller isLandscape is Bool.
Now FirstViewController.m file i want that in Portarit mode so used this code
- (IBAction)PlayClicked:(id)sender
{
AppDelegate * delegate=(AppDelegate *)[[UIApplication sharedApplication]delegate];
self.navigationController.navigationBarHidden=YES;
delegate.islandscape=YES;
ViewController * v=[[ViewController alloc]initWithNibName:#"ViewController" bundle:nil];
[self presentViewController:v animated:NO completion:nil];
//[self dismissViewControllerAnimated:YES completion:nil];
[self.navigationController pushViewController:v animated:YES];
}
- (NSInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait;
}
and SecondViewController i want that in Landscape mode used this one.
delegate.islandscape=NO; // called transfer to Category
- (NSInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskLandscape;
}

preferredInterfaceOrientationForPresentation not getting called

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)

Resources