Fixed orientation for a view controller - objective-c

In my app I've a UITabBarController that contains 3 UINavigationController. I can freeze orientation for any UIViewController. For this I've implemented UITabBarController and UINavigationController. But problem occurs when I push a UIViewController from another one that was in Landscape. The newly pushed UIViewController should be in portrait but it remains in Landscape. I know problem may be unclear so I am attaching scrrenshots.
Lets consider its VC-A.
Pressing edit from VC-A goes to this VC-B. VC-B is:
This VC-B should always in portrait. VC-A can be in Landscape or portrait. When VC-A is in landscape and I press edit the VC-B is pushed and VC-B comes in landscape mode though I implemented these methods in VC-B:
-(BOOL)shouldAutorotate {
return UIInterfaceOrientationMaskPortrait;
}
-(NSUInteger)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskPortrait;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
return UIInterfaceOrientationPortrait;
}

Your shouldAutorotate needs to return a BOOL not the mask, so code should be
-(BOOL)shouldAutorotate {
return YES;
}

All child view controllers in a tab bar controller or navigation controller must have the same set of supported orientations. This is discussed near the bottom of the following document.
https://developer.apple.com/library/ios/qa/qa1688/_index.html

Related

Fix Status Bar even in Landscape

I have a ViewController inside a UINavigationController and only this navigationController in my app is in portrait. So i forced it to be
always in portrait implementing in my NavigationController the following methods:
(UIInterfaceOrientationMask)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskPortrait;
}
(BOOL) shouldAutorotate {
return NO;
}
So it works to force my NavigationController be always in portrait programmatically. But when a change to landscape in simulator my status bar disappear. I want to keep my status bar appearing in portrait mode even if i change it to landscape ( its not a landscape at all, it is a rotation ).
I've tried a lot of things with no result.
Thanks

How to setting orientation for each ViewController in Tabbed Application in iOS7?

In the Tabbed Application I have two View.
I want to fix the firstView to portrait and the seccondView can rotate to portrait and landscape.
I implement the code below in firstViewController.
- (NSUInteger)supportedInterfaceOrientation {
return UIInterfaceOrientationMaskPortrait;
}
The code in secondViewController is
- (NSUInteger)supportedInterfaceOrientation {
return UIInterfaceOrientationMaskAllButUpsideDown;
}
But when I rotate my phone, the setting have no working.
Cloud somebody can tell my how to do that.
You need to subclass your UINavigationController and UITabBarController. Take a look at this questions, it is essentially the same shouldAutorotate, supportedInterfaceOrientations and preferredInterfaceOrientationForPresentation does not work as expected in iOS 7

launching a modal view controller to work around the orientation "lock" of tab bar and nav VCs?

I have an iPhone app with a root view controller (VC) of UITabBarController (set to portrait orientation) with several tabs, one of which is a simple UIViewController. In that UIViewController is a single button - "Play Video", which, when clicked opens a modal view of the video (and automatically starts playing the video). The video view is a UIWebView in a UIViewController. I've been trying to get the Web View's VC to change orientation to landscape but have not had any luck.
I've looked around and understand that if you have a Tab Bar or a Nav controller, all children VCs will be the same orientation as the parent - makes sense. This is why I made the web view's VC modal, hoping this is a way around the orientation issue.
My question is: is this accurate - that using modal will not require the web view VC to be portrait and can respond to the shouldAutorotateToInterfaceOrientation method (even though I have not yet been able to get it to work)?
BTW, using iOS 6.
Thanks in advance.
Apparently in ios6 and above, the way rotation works is different. So what you have to do is the following
In your .plist support all 4 orientations.
Subclass the UITabBarController (for e.g: CustomTabBarController)
In the CustomTabBarController put the following lines of code
-(NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return UIInterfaceOrientationPortrait;
}
In your app delegate or where ever you are initializing UITabBarController, replace those instances with CustomTabBarController instances.
In your modal controller put the lines
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return UIInterfaceOrientationLandscapeLeft;
}
-(BOOL)shouldAutorotate{
return NO;
}
And it should all work.
Apparently the trick, I found is that, UITabBarController will not listen to your instructions. It will support all the orientations you mention in the .plist.
There fore you have to subclass it.
I tried doing all of the above and it works fine. Do let me know and I can send you the code if you want.
Try this. Just have portrait set in the summary screen, then in the app delegate, implement this:
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
return UIInterfaceOrientationMaskAll;
}
In the tab bar controller (and no other rotation code):
-(BOOL)shouldAutorotate {
return NO;
}
And finally, in the modal view controller:
-(BOOL)shouldAutorotate {
return YES;
}
- (NSUInteger)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskAll;
}

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.

Force rotation of a UIViewController in a NavigationController in a TabbarController

I've got my View hierarchy set up like this.
UITabBarController
|
UINavigationController
| |
| UIViewController
|
UINavigationController
|
UIViewController
The thing is that I have a ViewController that is only shown in Portrait, as soon as I turn the device to landscape another ViewController is being pushed on top, that is working as intended so far.
What I want now is that as soon as I push the back button on the newly popped ViewController that the old ViewController is being forced to Portrait, even though the Device is still in Landscape.
I have tried it with transitions, but then the other views are getting screwed and don't properly recognize there orientation anymore leading to a mess of displaced views.
The only thing that worked for me was using
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationLandscapeLeft || interfaceOrientation == UIInterfaceOrientationLandscapeRight);
}
in my ViewController and presenting it with presentModalViewController.
This forces the View to stay in landscape.
Not exactly what I wanted, but it worked out.
Try adding this to your original view controller:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
if (UIInterfaceOrientationIsPortrait(interfaceOrientation)) return YES;
return NO;
}
This should force it to only display in portrait orientation.
The code below will force the view into landscape mode, but only if the parent view controller supports landscape mode.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationLandscapeLeft || interfaceOrientation == UIInterfaceOrientationLandscapeRight);
}
If the parent view controller of the view you want to force into landscape mode is portrait only, you'll have to create a new new navigation controller. The easiest way to do that is just presenting the forced-landscape view controller in a modal view. So use presentModalViewController instead of pushViewController.