I often see code like this:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
return YES;
}
If the supported orientation is set in the project configuration, wouldn't just returning YES all the time be pointless? Or are there certain cases where this has an effect?
shouldAutorotateToInterfaceOrientation: (which is deprecated since iOS 6, by the way) is something completely different than the UISupportedInterfaceOrientations in the info plist! If you don't implement this method, the respective view controller won't ever autorotate to that interface orientation, no matter what you specify in UISupportedInterfaceOrientations.
From the documentation of UISupportedInterfaceOrientations:
The system uses this information (along with the current device orientation) to choose the initial orientation in which to launch your app.
Maybe in many parts of your application you support multiple interface orientations, but in one part you only support some of them (for example you want a video only to play in landscape)
So even if your app supports portrait, you probably want that the viewcontroller makes the orientation landscape
Edit: i'm commenting here because I can't comment other answers.
#daniel-rinser in iOS6, the system checks for project supported interface orientations, and intersects with viewcontroller's supported orientations, so it isn't only for launch but for all app execution.
Related
Technical Note TN2244: Launching your iPhone Application in Landscape states:
The values of the UISupportedInterfaceOrientations key determine how the status bar is positioned while the the app is launching. In iOS 7 and below, if the UIInterfaceOrientationPortrait value is present, the status bar will always be positioned for portrait orientation. Otherwise, the status bar will be positioned according to the first orientation that appears under the UISupportedInterfaceOrientations key.
So in iOS 8 it was perfectly fine to put UIInterfaceOrientationLandscape first in the UISupportedInterfaceOrientations list to have your app to start in Landscape.
It does not work anymore in iOS 9. Having UIInterfaceOrientationPortrait in the list at any position forces app to start in Portrait.
Question
Is there a known workaround for this? I need my app to start in Landscape.
Note: Using viewControllers' supportedInterfaceOrientations() method is not an option as it takes effect after the LaunchScreen is presented.
Having UIInterfaceOrientationPortrait in the list at any position forces app to start in Portrait.
That is absolutely correct — very good detective work. It took me a lot of experimentation to figure this out! This is certainly a huge change from iOS 8. You have summed up the situation very well.
Fortunately, the workaround is simple. In your Info.plist, include only the two landscape orientations. Now the app will launch into whichever one is first.
Now implement application:supportedInterfaceOrientationsForWindow: in the app delegate to return All. That way, when the time comes to show a portrait view controller, it will be legal to do so.
In other words, think of the Info.plist as what the launching app needs to know, and application:supportedInterfaceOrientationsForWindow: as what the running app needs to know.
This question already has answers here:
Portrait mode only-iOS
(2 answers)
Closed 9 years ago.
First time developer and have just setup the certificates to be able to run my application on an iOS device.
My application does not view nicely in landscape mode even with Autolayout setup. How can I disable the user from being able to view the app in landscape when they turn the device? i.e. its always portrait regardless of the orientation of the device? thanks
EDIT: Does Apple also advise against doing this during submission?
As Siavash said, the General Tab in your Target is the best place to limit the orientations for the entire device.
If you wanted to set all orientations possible but limit it for certain View Controllers, you could do something like this:
- (BOOL) shouldAutorotate
{
return NO;
}
- (BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
{
return NO;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
if (condition)
{
return UIInterfaceOrientationPortrait;
}else{
return UIInterfaceOrientationLandscapeLeft;
}
}
To answer your second question, Apple does not critique an app based on its possible orientations. It's more up to you to decide which orientation(s) is/are best suited for your app. For iPhone Apps, users prefer Portrait usually for example (unless it's a game!).
The easiest way is to go to your project file and under the Deployment info part, check the orientation that you want to have for each device.
Edit:
Here is the picture for your reference:
The easiest way to do this (no code required) is to go into your app's info.plist file, look for an entry called "Supported interface orientations" (Key = "UISupportedInterfaceOrientations"), click on it's disclosure triangle to display the list of supported orientations, and delete both landscape orientations.
That will prevent your entire app from switching to landscape.
If you want some view controllers to support different orientations then the supportedInterfaceOrientations method (new in iOS 6) is the way to go. The other poster's code using shouldAutorotateToInterfaceOrientation is for iOS 5.x and older.
I want to have my app always in portrait mode facing up. That means that if the device it tipped to passed perpendicular to the floor and is starting to face the floor, it will readjust so it functions like it is in portrait mode facing upward. The same with if the device starts to be portrait upside-down, it will be portrait facing up (tilted upward. I have placed this in my apps delegate
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
under the -(BOOL) application did finishLaunching etc. but I need to know what I need to put into the delegate so throughout the app the above is always true.
Anyone help.
You specifying all required orientations in your Info.plist file as Array with a key UISupportedInterfaceOrientations Limit the list of supported orientation to the orientation that you want. beginGeneratingDeviceOrientationNotifications is very specific method that required for a unique use-cases but not for general orientation handling. Here is some of examples where beginGeneratingDeviceOrientationNotifications could be useful, but it is definitely not your case - How to handle autorotation in AVCaptureVideoPreviewLayer?
You can set this in your project's deployment info in Xcode.
I think you also need to implement shouldAutorotate and supportedInterfaceOrientations in your UIViewControllers. This Apple reference doc should help: UIViewController Class Reference.
Also, here's a similar question and answer.
Seems like a simple thing to do right? Go to the Target's Summary tab and set "Supported Interface Orientations" to Landscape Right only. You would think that would mean the app would be landscape only. But no.
On a device running 5.1 for example, if you open the app and hold the phone in the correct landscape right position you will see the view rotated 90 degrees counterclockwise, as if it think it's supposed to be in portrait mode, unless you add something like this:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return UIInterfaceOrientationIsLandscape(interfaceOrientation);
}
But that only works for one view controller, and who knows if it works on all OS versions.
So how do you make an app landscape only? Do I have to add that code to every single view controller in the app? I do not need any rotation. All my views are designed in Landscape. I just want the app to open in Landscape Right mode and stay that way. And I want to support iOS 5 and up.
There are new methods introduced that you have to implement along with the old one they are as below
-(BOOL)shouldAutorotate
{
return YES;
}
-(NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskLandscape;
}
In Xcode you can navigate to your project settings -> summary -> iPhone/iPod deployment info. Here you can select the supported interface orientations. You can also edit the 'Supported interface orientations' array in your application's info.plist by adding the desired interface orientations application wide.
In the info.plist put the orientation to landscape
I am looking for some clarification on how to allow only certain orientations for your iOS app. I am aware of UISupportedInterfaceOrientations and shouldAutorotateToInterfaceOrientation but I am a little confused on their uses and exactly how they fit together.
I attempted to use UISupportedInterfaceOrientations to only allow landscape orientations, which appeared to have no affect until I researched in to it and read that it affects the initial orientation. Upon testing this, my app does appear to only open in landscape but quickly rotates if the screen is portrait.
I know you can use shouldAutorotateToInterfaceOrientation to limit the allowed orientations, for example:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return (interfaceOrientation == UIInterfaceOrientationLandscapeLeft) ||
(interfaceOrientation == UIInterfaceOrientationLandscapeRight);
}
However, while doing some reading online I read shouldAutorotateToInterfaceOrientation is deprecated as of iOS6.
Basically my questions are:
What is the correct approach for limiting screen orientations across
multiple versions of iOS?
Is the only use of UISupportedInterfaceOrientations to limit the
initial orientation?
Edit:
To expand on the accepted answer, shouldAutorotate works in iOS6. As a quick fix if you've already implemented your logic in shouldAutorotateToInterfaceOrientation and/or you want to support earlier versions of iOS, you can do the following:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return (interfaceOrientation == UIInterfaceOrientationLandscapeLeft) ||
(interfaceOrientation == UIInterfaceOrientationLandscapeRight);
}
- (BOOL)shouldAutorotate {
return [self shouldAutorotateToInterfaceOrientation:self.interfaceOrientation];
}
The method you need to use for rotation instead of shouldAutorotateToInterfaceOrientation is just shouldAutorotate
Handling rotation, according to the AppleDoc for ViewControllers:
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.
The method shouldAutorotateToInterfaceOrientation is deprecated, as are some methods for handling responses to device rotation.
For supporting methods of multiple versions of iOS, Here's something else that Apple has said:
For compatibility, view controllers that still implement the shouldAutorotateToInterfaceOrientation: method do not get the new autorotation behaviors. (In other words, they do not fall back to using the app, app delegate, or Info.plist file to determine the supported orientations.) Instead, the shouldAutorotateToInterfaceOrientation: method is used to synthesize the information that would be returned by the supportedInterfaceOrientations method.
Taken from release notes
To answer your second question:
Yes, the "UISupportedInterfaceOrientations" entry in the Info.plist is used only for initial startup of your app, making sure it doesn't start your app in an orientation it doesn't support, so that it's not required to perform a rotation right away.
Also, overriding "application:supportedInterfaceOrientationsForWindow" in your AppDelegate is pretty useful if your app never wants to use particular orientations (e.g. for a game that only does landscape).
Lastly, and this is a common error, on iPhone and iPod Touch devices, the device should never rotate to UIInterfaceOrientationPortraitUpsideDown! That's because these devices (contrary to an iPad) do not let the user lock a device in landscape mode with the Lock soft button - that button only locks into portrait. Therefore, if a user, laying on his side, wants to use an app in landscape mode, he cannot do this if your app goes into the upside down orientation. But if you disallow that rotation, then it works.