force UIViewController to be in Landscape mode iOS7 - objective-c

I've implemented the proper functions, but they don't get triggered? I've tried several solutions here on StackOverFlow, but none of them work. I've tried adding the view to a UINavigationController, also doesn't work.
FakeIDDetailViewController.h:
#interface FakeIDDetailViewController : UIViewController
#end
FakeIDDetailViewController.m:
#interface FakeIDDetailViewController ()
-(BOOL)shouldAutorotate
{
return NO;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (UIInterfaceOrientationMaskLandscapeLeft);
}
-(NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskLandscapeLeft;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return UIInterfaceOrientationLandscapeLeft;
}
- (NSUInteger) application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
return UIInterfaceOrientationLandscapeLeft;
}

If you are pushing a view controller to a stack of other view controllers in a navigation controller, requiring landscape only will not work well. You should display the landscape-constraint view controller modally.
See my answer here for an example project:
https://stackoverflow.com/a/16022631/983912

For a navigation controller interface, forcing an orientation is not supported by the framework. See my answer here: https://stackoverflow.com/a/15301322/341994
For a workaround (not very good), see my answer here: https://stackoverflow.com/a/16379515/341994
However, forcing an orientation works fine for a presented view controller.

Related

How to stop to rotate one view controller with uinavigationcontroller? [duplicate]

This question already has an answer here:
How to set one of the screens in landscape mode in iphone?
(1 answer)
Closed 8 years ago.
hey guys i have seen many similar question but could not reach to any solution. I am creating an universal app using storyboard and having a navigation controller which is having root view controller v1, so initially top view controller is v1. And on clicking a button on v1 it push view controller v2. Now i want that app should rotate in all direction for all view controllers except view controller v2. I have checked all device directions in deployment info and also tried to create category of uinavigationcontroller
#import <UIKit/UIKit.h>
#interface UINavigationController (autorotation)
-(BOOL)shouldAutorotate;
-(NSUInteger)supportedInterfaceOrientations;
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation;
#end
#import "UINavigationController+autorotation.h"
#import "AboutViewController.h"
#implementation UINavigationController (autorotation)
-(NSUInteger)supportedInterfaceOrientations
{
return [self.topViewController supportedInterfaceOrientations];
}
-(BOOL)shouldAutorotate
{
return [self.topViewController shouldAutorotate];
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return [self.topViewController preferredInterfaceOrientationForPresentation];
}
MY problem is that app is rotating for all screens but i want to stop rotation for view controller v2 as described above. I really have my two days please help me
- (BOOL)shouldAutorotate
{
id currentViewController = self.topViewController;
if ([currentViewController isKindOfClass:[v2 class]])
return NO;
return YES;
}
//add this method in your code and tell me its work or not.
This is a useful link i used once it does the oposit of what you asked but still, you can use it.
Another way will be to put this in your view that you don`t want to rotate
- (BOOL) shouldAutorotate {
return NO; }
Don't forget to rotate the view to appropriate InterfaceOrientation, something like this
[self willAnimateRotationToInterfaceOrientation:1 duration:1];
you can put this in viewWillApear;

Force Landscape Orientation on iOS 6 in Objective-C

I have a master view controller that's inside a UINavigationController. In that master view controller, I have a button that pushes a detail view controller that has a UIWebView inside of it. I want this detail view controller to be on landscape mode when it's loaded. Going back to the master view controller, it forcibly goes back again to portrait mode. I'm running iOS 6 on this.
I have seen the other similar questions but it's not working on my end. I have created a LandscapeViewController that's a subclass of UIViewController where I have written these methods:
#pragma mark - Orientation Methods
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskLandscape;
}
- (BOOL)shouldAutorotate
{
return YES;
}
This is my code when I push the detail view controller:
DetailViewController *detailVC = [[DetailViewController alloc]
initWithNibName:#"DetailViewController"
bundle:nil];
[self.navigationController pushViewController:detailVC
animated:YES];
I'm thinking on where to subclass my LandscapeViewController on the code above to make it work or on how to properly subclass and push my detail view controller. I can also present my detail view controller modally if it's not possible for the navigation controller to push my detail view controller from portrait to landscape. Where am I doing it wrong?
Considering:
View A: Portrait only - View B: Landscape only
I couldn't do it in the navigation controller. Instead what I did was to open a modal view from view A to view B and force a new navigation controller into this view.
This is working for me in iOS5+.
You need to create a category for the navigation controller like this:
UINavigationController+Rotation_IOS6.h
#import <UIKit/UIKit.h>
#interface UINavigationController (Rotation_IOS6)
- (BOOL)shouldAutorotate;
- (NSUInteger)supportedInterfaceOrientations;
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation;
#end
UINavigationController+Rotation_IOS6.h
#import "UINavigationController+Rotation_IOS6.h"
#implementation UINavigationController (Rotation_IOS6)
- (BOOL)shouldAutorotate
{
return [self.topViewController shouldAutorotate];
}
- (NSUInteger)supportedInterfaceOrientations
{
return [self.topViewController supportedInterfaceOrientations];
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return [self.topViewController preferredInterfaceOrientationForPresentation];
}
#end
In AppDelegate.m add:
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window{
return UIInterfaceOrientationMaskAll;
}
Then in View A:
- (BOOL)shouldAutorotate {
return YES;
}
-(NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskPortraitUpsideDown;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return UIInterfaceOrientationPortrait;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait || interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown);
}
also in View A to open View B do this:
ViewB *vc = [[ViewB alloc] initWithNibName:#"ViewB" bundle:nil];
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:vc];
[self presentViewController:navigationController animated:YES completion:nil];
And, finally, in View B
- (BOOL)shouldAutorotate {
return YES;
}
-(NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskLandscapeRight | UIInterfaceOrientationMaskLandscapeLeft;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return UIInterfaceOrientationLandscapeRight;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationLandscapeRight || interfaceOrientation == UIInterfaceOrientationLandscapeLeft);
}
They kinda screwed the pooch in iOS 6 with regard to this. Here's what I've figured out so far:
First off, Apple added the "Supported Interface Orientations" buttons with Xcode 4.5. This corresponds to the "Supported interface orientations" attribute in _info.plist. These buttons must be toggled to the correct choices before any of the rest will work. (If the buttons seem to refuse to toggle it's likely because the info.plist is locked by CVS or some other process.)
Next, the property .window.rootViewController must be set, and must point to the "bottom" view controller in the stack. Generally this will be either a navigation controller or a tab controller.
If the desire is to disable all rotation, this can be done using the buttons, or one can implement, in the "bottom" view controller, the "shouldAutorotate" method and have it return NO. (If the method is omitted then the default is YES.)
In spite of having autorotation disabled with shouldAutorotate, if there is a MPMoviePlayerViewController being displayed, that will autorotate. Only toggling the supported interface orientation buttons appears to prevent this.
If one wants to conditionally autorotate other view controllers it gets messier. Basically, your "bottom" view controller must implement the supportedInterfaceOrientations method and return, based on the current topViewController, the appropriate bit mask. This can be done with a routine that queries the topViewController's old "shouldAutorotateToInterfaceOrientation" method, but it's a bit ugly. And even though this scheme doesn't require modifying the rotating view controller's code, you DO need to modify the VC just "below" the rotated one to implement "supportedInterfaceOrientation", or else that view will be rotated on return. (At least this is a simple copy/paste.) No one seems to have come up with a better, more general scheme, though.

Support different orientation for only one view iOS 6

I want to rotate ONLY one of my views within my app to either landscape left or landscape right. All my other views are in portrait mode and I have set my app to support only portrait mode. With orientation being changed in iOS 6, I am not sure how to do this. I have tried the following posted below. Can anyone tell me what I am doing wrong? Thanks!
-(BOOL)shouldAutorotate {
return YES;
}
-(NSUInteger)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight;
}
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return UIInterfaceOrientationMaskLandscapeRight | UIInterfaceOrientationMaskLandscapeLeft;
}
I have also tried:
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(didRotate:)
name:UIDeviceOrientationDidChangeNotification
object:nil];
return YES;//UIInterfaceOrientationMaskLandscapeRight | UIInterfaceOrientationMaskLandscapeLeft;
}
-(void)didRotate:(NSNotification *)notification {
UIDeviceOrientation orientation = [[notification object] orientation];
if (orientation == UIDeviceOrientationLandscapeLeft) {
[theImage setTransform:CGAffineTransformMakeRotation(M_PI / -2.0)];
[self.view setTransform:CGAffineTransformMakeRotation(M_PI / 2.0)];
} else if (orientation == UIDeviceOrientationLandscapeRight) {
[theImage setTransform:CGAffineTransformMakeRotation(M_PI / -2.0)];
[self.view setTransform:CGAffineTransformMakeRotation(M_PI / -2.0)];
} else if (orientation == UIDeviceOrientationPortraitUpsideDown) {
[theImage setTransform:CGAffineTransformMakeRotation(M_PI / -2.0)];
[self.view setTransform:CGAffineTransformMakeRotation(M_PI / -2.0)];
} else if (orientation == UIDeviceOrientationPortrait) {
[theImage setTransform:CGAffineTransformMakeRotation(M_PI / 2.0)];
[self.view setTransform:CGAffineTransformMakeRotation(M_PI / 2.0)];
}
}
This worked for me How to force a UIViewController to Portrait orientation in iOS 6
Create a new category from UINavigationController overriding the rotating methods:
-(BOOL)shouldAutorotate
{
return [self.topViewController shouldAutorotate];
}
-(NSUInteger)supportedInterfaceOrientations
{
return [self.topViewController supportedInterfaceOrientations];
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return [self.topViewController preferredInterfaceOrientationForPresentation];
}
#end
There are changes in iOS 6 regarding handling view rotations. Only orientations defined in apps Info.plist are supported. Even if you are returning other ones.
Try to select all orientations as supported in your project.
Handling View Rotations
In iOS 6, your app supports the interface orientations defined in your app’s Info.plist file. A view controller can override the supportedInterfaceOrientations method to limit the list of supported orientations. Generally, the system calls this method only on the root view controller of the window or a view controller presented to fill the entire screen; child view controllers use the portion of the window provided for them by their parent view controller and no longer participate in directly in decisions about what rotations are supported. The intersection of the app’s orientation mask and the view controller’s orientation mask is used to determine which orientations a view controller can be rotated into.
You can override the preferredInterfaceOrientationForPresentation for a view controller that is intended to be presented full screen in a specific orientation.
In iOS 5 and earlier, the UIViewController class displays views in portrait mode only. To support additional orientations, you must override the shouldAutorotateToInterfaceOrientation: method and return YES for any orientations your subclass supports. If the autoresizing properties of your views are configured correctly, that may be all you have to do. However, the UIViewController class provides additional hooks for you to implement additional behaviors as needed. Generally, if your view controller is intended to be used as a child view controller, it should support all interface orientations.
When a rotation occurs for a visible view controller, the willRotateToInterfaceOrientation:duration:, willAnimateRotationToInterfaceOrientation:duration:, and didRotateFromInterfaceOrientation: methods are called during the rotation. The viewWillLayoutSubviews method is also called after the view is resized and positioned by its parent. If a view controller is not visible when an orientation change occurs, then the rotation methods are never called. However, the viewWillLayoutSubviews method is called when the view becomes visible. Your implementation of this method can call the statusBarOrientation method to determine the device orientation.
(C) Apple Docs: UIViewController
Follow the below steps
Create subclass of UINavigationController overriding the rotating methods.
In AppDelegate, create a BOOL islandscape property.
When a view is pushed/poped/present/dismiss, adjust this BOOL value.
Sample Project
I created a sample project for this which is working perfectly. Download and integrate in your project: https://www.dropbox.com/s/nl1wicbx52veq41/RotationDmeo.zip?dl=0
I have a:
TabbarController -> NavigationController -> ViewController -> ViewController
I Subclassed UITabBarController and add....
-(NSUInteger)supportedInterfaceOrientations{
if (self.selectedIndex >= 0 && self.selectedIndex < 100) {
for (id vC in [[self.viewControllers objectAtIndex:(unsigned long)self.selectedIndex] viewControllers]) {
if ([vC isKindOfClass:[CLASS_WHICH_SHOULD_ALLOW class]]) {
return UIInterfaceOrientationMaskPortrait + UIInterfaceOrientationMaskLandscape;
}
}
}
return UIInterfaceOrientationMaskPortrait;
}
I have been searching for the solution for hours!
So after implementing the needed methods everywhere. shouldAutorotate doesn't need to be set to YES because it is already set as default:
- (NSUInteger)supportedInterfaceOrientations{
return UIInterfaceOrientationMaskPortrait;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation{
return UIInterfaceOrientationPortrait;
}
When it is time to show the UIViewController which needs the orientation different than the other views, I created a UIStoryboardSegue with this implementation inside:
#import "Showing.h"
#implementation Showing
- (void)perform{
NSLog(#"Showing");
UIViewController *sourceVC = self.sourceViewController;
UIViewController *presentingVC = self.destinationViewController;
[sourceVC.navigationController presentViewController:presentingVC
animated:YES
completion:nil];
}
#end
Inside the UIStoryboard I connected the views with this segue (showing):
It is just important, you are using
presentViewController:animated:completion:
AND NOT
pushViewController:animated:
otherwise the orientation won't be determined again.
I had been trying things like
[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait];
OR this one inside the UIViewController where the orientation should change, and I also tryied to call it inside my custom UIStoryboardSegues before presentingViewController and dismissViewController:
[UIViewController attemptRotationToDeviceOrientation];
OR
NSNumber *numPortrait = [NSNumber numberWithInt:UIInterfaceOrientationPortrait];
[[UIDevice currentDevice] setValue:numPortrait forKey:#"orientation"];
But no one of them worked. Of course the last example shouldn't be an option, because if apple will change anything of their api this could cause problems inside your app.
I also tried to use the AppDelegate method and always determine the orientation inside this method after looking for the correct UIInterfaceOrientation of the actual visibleViewController but then it sometimes happened to crash when switching from one to another orientation. So I'm still wondering why its made so complicated and there seems also not to be any documentation where it is explained correctly.
Even following this part didn't help me.
UIViewController+OrientationPermissions.h
#interface UIViewController (OrientationPermissions)
+ (void)setSupportedOrientations:(UIInterfaceOrientationMask)supportedOrientations;
+ (UIInterfaceOrientationMask)supportedOrientations;
#end
UIViewController+OrientationPermissions.m
#implementation UIViewController (OrientationPermissions)
static UIInterfaceOrientationMask _supportedOrientations;
+ (void)setSupportedOrientations: (UIInterfaceOrientationMask)supportedOrientations {
_supportedOrientations = supportedOrientations;
}
+ (UIInterfaceOrientationMask)supportedOrientations {
return _supportedOrientations;
}
#end
In your UIApplication delegate
- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
return [UIViewController supportedOrientations];
}
Then on a desired view controller do something like
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[UIViewController setSupportedOrientations:UIInterfaceOrientationMaskAll];
}
Don't forget to reset mask before leaving this view controller
Note, if you are using UINavigationController or UITabBarController, see https://stackoverflow.com/a/28220616/821994 how to bypass that
Defiantly work Please try.
I solve after 2 days
//AppDelegate.m - this method is not available pre-iOS6 unfortunately
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window{
NSUInteger orientations = UIInterfaceOrientationMaskAllButUpsideDown;
if(self.window.rootViewController){
UIViewController *presentedViewController = [[(UINavigationController *)self.window.rootViewController viewControllers] lastObject];
orientations = [presentedViewController supportedInterfaceOrientations];
}
return orientations;
}
//MyViewController.m - return whatever orientations you want to support for each UIViewController
- (NSUInteger)supportedInterfaceOrientations{
return UIInterfaceOrientationMaskPortrait;
}

iOS 6 Rotation issue - No rotation from Presented Modal View Controller

I have a MainViewController which has a button which pushes a new view (InfoViewController), via flip horizontailly. like so:
controller.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:controller animated:YES];
The MainView Controller supports Portrait and PortraitUpsideDown. Like so:
- (BOOL)shouldAutorotate {
return YES;
}
- (NSUInteger)supportedInterfaceOrientations {
return (UIInterfaceOrientationMaskPortrait |
UIInterfaceOrientationMaskPortraitUpsideDown);
}
In my InfoViewController it also states the above code. In my AppDelegate it has this in the LaunchOptions:
[self.window setRootViewController:self.mainViewController];
In my app.plist file it supports all orientations. This is because other views need to support landscape as well. So On my MainViewController and InfoViewController I need only Portrait and PortraitUpsideDown. But on another view I need all orintations.
My MainViewController works fine, but my InfoViewController is working for all orientations.
I am having extreme diffulty trying to get this to work in iOS6. I have researched other posts and tried the assistance other people have provided, but had no luck whatsoever. Please can someone help me acheive this thank you. And I'm a Objective-C newbie :p
Don´t support all orientations in your app plist file, only those that your root view controller supports.
Autorotation is changing in iOS 6. In iOS 6, the shouldAutorotateToInterfaceOrientation: method of UIViewController is deprecated. In its place, you should use the supportedInterfaceOrientationsForWindow: and shouldAutorotate methods:
- (BOOL)shouldAutorotate {
return YES;
}
- (NSUInteger)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskAllButUpsideDown;
}
Modal ViewControllers no longer get rotation calls in iOS 6:
The willRotateToInterfaceOrientation:duration:,
willAnimateRotationToInterfaceOrientation:duration:, and
didRotateFromInterfaceOrientation: methods are no longer called on any view controller that makes a full-screen presentation over
itself—for example those that are called with: presentViewController:animated:completion:.
You can let the view controller that presents your modal view controller inform it of rotation.
Also, now you use: presentViewController:animated:completion: to present the view controller. presentModalViewController:animated: is deprecated which you use in the code.
I have solved similar problems, while using tab bar controller.
Subclass UITabBarController. Implement these methods:
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskAll;
}
- (BOOL)shouldAutorotate
{
NSLog(#"Orientation:%d", [[UIDevice currentDevice] orientation]);
for (UIViewController *viewController in self.viewControllers) {
[viewController shouldAutorotate];
}
return YES;
}
If you want to handle rotations in controllers inside tabbarcontroller, in each of the controllers in the tab bar controller implement those methods too and write code to handle orientation change. If you don't want to handle it, then you don't need to implement those methods. TabBarControllers methods will always run when orientation changes. Even twice for unknown reason.
Yes, and don't forget to delete all shouldAutorotate methods. I moved to the new orientation model completely. If you want to make them remain, probably, it will be harder.
Make a category by subclassing UINavigationController and implement following methodes
in .h file
-(BOOL)shouldAutorotate;
-(NSUInteger)supportedInterfaceOrientations;
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation;
in .m file
-(BOOL)shouldAutorotate
{
return [self.topViewController shouldAutorotate];
}
-(NSUInteger)supportedInterfaceOrientations
{
return [self.topViewController supportedInterfaceOrientations];
}
-(UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return [self.topViewController preferredInterfaceOrientationForPresentation];
}
and implement following methodes in the view controller class ,class u want to enable rotation
-(NSUInteger)supportedInterfaceOrientations
{
return (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight | UIInterfaceOrientationMaskPortraitUpsideDown);
}
- (BOOL)shouldAutorotate
{
return YES;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return UIInterfaceOrientationLandscapeLeft;
}
add this code on Subclass UITabBarController .m
#implementation UINavigationController (rotation)
//temp hack for iOS6, this allows passing supportedInterfaceOrientations to child viewcontrollers.
- (NSUInteger)supportedInterfaceOrientations {
return [self.topViewController supportedInterfaceOrientations];
}
#end
#implementation NameClassUITabBar
- (void)viewDidLoad {
[super viewDidLoad];
}
- (BOOL)shouldAutorotate
{
return YES;
}
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskLandscape;
}
#end
Here I've posted my solution/experince in tab bar controller with rotations:
http://luterr.blogspot.sg/2015/04/example-code-uiinterfaceorientationmask.html

Device Orientation not working for my app

I am having problem in implementing the device orientation methods. I am implementing it as
follows
-(BOOL)shouldAutorotate{
return TRUE;
}
-(NSUInteger)supportedInterfaceOrientations{
return UIInterfaceOrientationMaskAll;
}
In tha appdelegate I am doing
self.window.rootViewController = self.splitViewController;
I want my app to work for all the orientations . But none of the orientation is working
properly.Any help ? My app is targeted IOS 4.3 , but it should also work for IOS 5 and 6 as well.
First of all, in AppDelegate, write this. THIS IS VERY IMP
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
return (UIInterfaceOrientationMaskAll);
}
Also, A lot depends on with which controller is your UIViewController embedded in.
Eg, If its inside UINavigationController, then you might need to subclass that UINavigationController to override orientation methods like this.
subclassed UINavigationController (the top viewcontroller of the hierarchy will take control of the orientation.) needs to be set it as self.window.rootViewController.
- (BOOL)shouldAutorotate
{
return self.topViewController.shouldAutorotate;
}
- (NSUInteger)supportedInterfaceOrientations
{
return self.topViewController.supportedInterfaceOrientations;
}
From iOS 6, it is given that UINavigationController won't ask its UIVIewControllers for orientation support. Hence we would need to subclass it.