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

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;

Related

force UIViewController to be in Landscape mode iOS7

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.

Really Stuck on Screen Rotation iOS 6, I Need a xib locked to portrait

Having read every method of handling screen rotation in IOS 6 on here, Apple documents, and fierce Googling, after days and days I am still stuck on this when using xibs.
What im trying to achieve is have a few iPad only xibs, in landscape only, rest of app is portrait.
If I was using storyboards I understand how to subclass the nav controller to override the rotation but I am NOT, im using xibs and would appreciate any input how this works with xibs
In my app delegate:
ICHomeController *homeController = [[ICHomeController alloc] init];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:homeController];
navController.navigationBarHidden = YES;
navController.navigationBar.barStyle = UIBarStyleBlackOpaque;
navController.navigationBar.tintColor = [UIColor grayColor];
self.navigationController = navController;
[self.window setRootViewController:self.navigationController];
[self.window makeKeyAndVisible];
return YES;
In addition to trying what seems like every solution on here Ive tried the obvious in my vew controllers, but as I understand in iOS 6 it doesn't get called.
// Older versions of iOS (deprecated)
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
return UIInterfaceOrientationIsLandscape(toInterfaceOrientation);
}
- (BOOL)shouldAutorotate {
return YES;
}
- (NSUInteger)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskLandscape;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
return UIInterfaceOrientationLandscapeLeft;
}
I've been battling with this for days too with a more complex navigation structure.
The basic rule seems to be that the ROOT controller, whether it be a UINavigationController, UITabBarController or just a simple UIViewController, takes control of the rotation. So as you PUSH UIViewControllers onto the stack, the very first one still controls the rotation.
If you use a modal view, then this model view will be considered the ROOT of the stack until it is dismissed. So if you show a modal UIViewController then push views on top of it, the UIViewController that was presented as the modal view is in control of the rotation.
Just make sure for modal views to use presentViewController:animated:completion.
The easiest way to get certain views to be in a different rotation, is present it modally.
If this can't be avoided, then go right back to your first view or nag controller and set the rotations.
Add some NSLog(#"%s", __FUNCTION__); statements to your rotation methods to see which ones are being called.
In your code above, only the first method is the old iOS5 (Now deprecated) method. The other 3 are the new iOS 6 methods.
Using your example code above, you would need to subclass the UINavigationController. To do this create a new class as a UINavigationController subclass with a different name eg. MyNavigationController and add the rotation methods to it. Then in your code above instead of using
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:homeController];
You would use:
MyNavigationController *navController = [[MyNavigationController alloc] initWithRootViewController:homeController];
Also, make sure you have allowed orientations selected here:
I had the same problem. Here's what worked for me in 5 and 6.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
return (toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft || toInterfaceOrientation == UIInterfaceOrientationLandscapeRight);
}
- (BOOL)shouldAutorotate NS_AVAILABLE_IOS(6_0)
{
return NO;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation NS_AVAILABLE_IOS(6_0) {
return UIInterfaceOrientationLandscapeLeft;
}
In terms of the target summary, only portrait mode is "supported".

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.

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.