My project set supported interface orientations to UIInterfaceOrientationMaskPortrait.
When I use presentMoviePlayerViewControllerAnimated: popup an MPMoivePlayerViewController, on IOS5 when I turn device, the controller will do auto orientation rotation, but on IOS6 it is always at portrait direction.
How can I make it act as IOS5?
Apple changed the way orientations are handle in iOS 6:
Controlling What Interface Orientations Are Supported (iOS 6)
When UIKit receives an orientation notification, it uses the
UIApplication object and the root view controller to determine whether
the new orientation is allowed. If both objects agree that the new
orientation is supported, then the user interface is rotated to the
new orientation. Otherwise the device orientation is ignored.
When a view controller is presented over the root view controller, the
system behavior changes in two ways. First, the presented view
controller is used instead of the root view controller when
determining whether an orientation is supported. Second, the presented
view controller can also provide a preferred orientation. If the view
controller is presented full screen, the user interface is presented
in the preferred orientation. The user is expected to see that the
orientation is different from the device orientation and rotate the
device. A preferred orientation is most often used when the content
must be presented in the new orientation.
So if your application is set to allow only portrait mode, you'll never get into landscape mode regardless of what any controller 'sais'.
See Controlling What Interface Orientations Are Supported (iOS 6) for more information.
Related
I'm working with Xamarin and am having troubles launching my app in the current device orientation.
I have a UINavigationController that I set on my main UIWindow as the root controller. I created a custom UINavigationController which overrides the methods :
GetSupportedInterfaceOrientations
and
ViewWillTransitionToSize
If I hold my iPad in landscape mode and start the app, it will start in portrait mode and then rotate in landscape. I'd like to make it start in the same orientation as the device's physical orientation. From the doc I've read it seems that since iOS 8, everything related to rotations should be handled in the root uiview controller which is my custom UINavigationController.
And here's my problem... let's say I want to start my app in the current device's orientation and then block everything except Portrait once the app is loaded. I tried the 2 following solutions and none worked.
1- I put all interface orientations available in the supported interface orientations key in the info.plist file. I launched the app while holding the iPad in landscape mode. In this case, my app starts in the same orientation as the device which is cool. What is not cool is that it doesn't call my navigation controller method GetSupportedInterfaceOrientations anymore. So even if I change the return value of that method to Portrait only later one, it does absolutely nothing since the method is never called anymore.
2- I removed all supported interface orientations from the info.plist file. I lauched the app while holding the iPad in landscape mode. In this case, my app starts in portrait mode and then rotates to landscape. I want to prevent the rotation and just start the app in the current device's orientation (landscape). With this setup though, I can later change the supported orientation as the navigation controller method GetSupportedInterfaceOrientations is being called everytime we try to rotate the app.
In apple's doc, it says "At launch time, apps should always set up their interface in a portrait orientation. After the application (_:didFinishLaunchingWithOptions:) method returns, the app uses the view controller rotation mechanism described above to rotate the views to the appropriate orientation prior to showing the window."
The part where the view rotates to the appropriate orientation PRIOR to showing the window doesn't seem to work for me. It shows the window and then rotates it after.
So how do you launch an app in the current device's orientation (without the user seeing your first view rotate from portrait to whatever) and then be able to change the supported orientations later in the app? Example : I hold my iPad in landscape mode. I launch my app. First view I see is already in landscape mode. I can then rotate my iPad to change the view in portrait/landscape back and forth. Then I click a button which changes the supported orientation to Portrait which prevents me from changing the orientation to Landscape anymore.
Thanks!
I am currently writing an iOS app in which have the acceptable device orientations set to Landscape Right and Landscape Left, and in all of my view controllers, I’m returning only those two in the supportedInterfaceOrientations method.
However, if the user uses the in-app camera functionality (which is implemented via UIImagePickerController presented modally in full screen) and rotates the device to Portrait orientation to take a picture, the camera rotates to portrait mode (which is fine), and if the user clicks "Use Photo", when the modal view is dismissed, the view from which the camera was launched is somehow now in portrait mode (which is not fine).
After the camera view has been dismissed, the view controller from which it was launched has UIDeviceOrientationIsPortrait set to true. I am wondering how it ended up in this orientation, and how when a picture is taken, I can ensure that the presenting view controller remains in a landscape orientation. Any help is greatly appreciated!
I am currently writing an iOS app in which have the acceptable device
orientations set to Landscape Right and Landscape Left, and in all of
my view controllers, I’m returning only those two in the
supportedInterfaceOrientations method.
In iOS 6 and later, your app supports the interface orientations defined in your app’s Info.plist file
Have you tried setting it here? Then see if the problem still occurs.
Also, if this doesn't work, try setting the supportedInterfaceOrientations values in the viewWillAppear method of the ViewController that launched UIImagePicker?
I am almost done developing an app. Right now I'm converting it to a universal app by supporting iPad to supported devices as well.
Can I set the app to use Landscape orientation only, since I am using UISplitViewController and want the Master View Controller to remain on the screen all the time? Is there any Apple policy that states that I cannot restrict it to Landscape only and I have to implement both portrait and landscape? Is there any chance my app can be rejected by setting it to Landscape only for iPad?
Don't worry, you'll be fine. Support both landscape orientations and neither portrait orientation if you want. I've got apps in the store that are like that.
However, note that UISplitViewController does have an option to keep both views on the screen all the time even in portrait. Use the delegate method splitViewController:shouldHideViewController:inOrientation: to forbid hiding the master view:
http://developer.apple.com/library/ios/#documentation/uikit/reference/UISplitViewControllerDelegate_protocol/Reference/Reference.html#//apple_ref/occ/intf/UISplitViewControllerDelegate
So if your only reason for being landscape only is that you don't want to hide the master view, it is a false reason. Look, for example, at Apple's Settings app, which works like that; it is a split view controller that always shows both views in all four orientations.
I made my gles app, and tested it on my iPad. It is supposed to work only on landscape mode, so I have my Info.plist like this
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
I set landscape-right only for iPhone so the splash screen shows correctly (it seems you can't set separate splash screens for landscape-right and landscape-left on the iPhone)
The application runs fine, but on a friend's iPhone, the app runs on portrait mode, and won't rotate to either landscape. The rotation lock is off.
I am not doing anything in particular from my code to support rotations, as just setting my Info.plist worked perfectly on my iPad.
The iPhone simulator automatically turns to landscape, and retains the landscape rendering even if I rotate it.
What could be causing this? I also tried allowing both landscape rotations, but no dice.
ios6 introduced new ways to deal with orientation changes - I'd guess your friend's iphone is running ios5. See the UIViewController docs to see how to deal with both versions:
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.
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.