If you are making AIR native extensions which use any form of native window, you may notice one of two things:
- The native window seems to have a mind of its own when it comes to orientation. In other words, if you want to keep your app Landscape only, the minute a native window shows up, the whole app may change its orientation to Portrait.
- The native window seems to have acquired a mind of its own. You had the native code all nicely set up, so that native and AIR views play nicely together and agree to orientation, but after moving to iOS 6, anarchy rules again.
How to ensure native windows don’t mess up your app’s orientation on iOS 6
Here is the recipe: override supportedInterfaceOrientations in your window’s implementation in your XCode project and have it return UIInterfaceOrientationMaskAll:
[sourcecode language=”objc”]
– ( NSUInteger ) supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskAll;
}
[/sourcecode]
The equivalent on iOS 5 was shouldAutorotateToInterfaceOrientation, which was deprecated in the iOS 6 SDK:
[sourcecode language=”objc”]
– ( BOOL ) shouldAutorotateToInterfaceOrientation : ( UIInterfaceOrientation ) toInterfaceOrientation
{
return YES;
}
[/sourcecode]
Wait, I don’t have access to the native window’s implementation!
There is a way out of this situation too: add a category to UIViewController and override supportedInterfaceOrientations in the category.
Categories in Objective-C are a way of adding or overriding methods in existing classes without subclassing them.
In this case UIViewController.
Make sure you import the class category in your code, in order for the overridden method to be called:
Why return UIInterfaceOrientationMaskAll if I want to restrict my app to Landscape only?
Kudos to you for asking this question! Like you, in DiaDraw we hate having to copy-paste recipes without knowing why they work.
An AIR Native Extension will typically present a view controller which is child of the root view controller, i.e. the controller of your AIR main window. When a root view needs to be rotated, it asks its children (subviews) which orientations they support. If the orientation that the view was headed for is not supported by a child, the rotation is overridden towards whatever orientation the child supports.
If child and root view controller don’t have any orientations in common they support, an exception is thrown and your app crashes.
Where can I see examples?
We have updated our Open-Source native extensions to play nicely with orientation on iOS 6. Two of these are a good example of the two cases in which child view controllers have to be set up to support all orientations:
I would like to add something…
Please do, join the conversation and share your experience with native extensions by leaving a comment below:
Radoslava, thank you for this post and sharing it with me via Google +.
For any others interested in the issue, or in case anyone else runs into the same problem here is the description and fix:
In the process of updating an older AIR application to target the iOS 7 SDK, I ran into a rather strange problem. On an iPad 2 running iOS 5, the default launch image was being rotated from landscape to portrait and somewhat skewed during the application launch process.
Here are a few of the basics of my application:
• Auto orients needed to be true ( landscape orientation only )
• Full screen true
• Application contained three iOS ANE files ( 1 JPEG Encoder, 1 Native Mail Composer, 1 Native Video Player )
• The Native Mail Composer and Native Video Player ANE’s use a UIViewController and I tested that the default launch orientation was only a problem when including one or both of the ANE’s that used the UIViewController. If I excluded those ANE’s and recompiled the application, the app launched as expected in landscape only even on the iOS 5 device.
• If I set auto orients to false in the app XML to debug the problem and still include the ANE files, the app would still auto orient which doesn’t make any sense, and if I set auto orients to false and removed the ANE’s that used the UIViewController the app would NOT auto orient which would be the expected behavior.
The application launched and ran as expected on iOS 6 and iOS 7, however as noted above the application’s “Default-Landscape~ipad.png” image rotated to portrait and became distorted/skewed on the iPad 2 running iOS 5. Prior to Radoslava helping me over Google +, I had already had a UIViewController Category class setup in Xcode called “UIViewController+Orientation”. The problem however is that the two methods I had in that Category class were not doing the trick. Radoslava’s example above uses the “supportedInterfaceOrientations” and “shouldAutorotateToInterfaceOrientation” methods. My previous Category class was using “_preferredInterfaceOrientationGivenCurrentOrientation” and “_isSupportedInterfaceOrientation”.
That previously used Category implementation I was using looked like this ( I had used this code when initially publishing this application a couple years ago ) :
– ( UIInterfaceOrientation ) _preferredInterfaceOrientationGivenCurrentOrientation : ( UIInterfaceOrientation ) interfaceOrientation
{
switch ( interfaceOrientation )
{
case UIInterfaceOrientationPortrait:
case UIInterfaceOrientationPortraitUpsideDown:
{
return UIInterfaceOrientationLandscapeLeft;
}
default:
{
return interfaceOrientation;
}
}
}
– (BOOL) _isSupportedInterfaceOrientation : ( UIInterfaceOrientation ) interfaceOrientation
{
return ( UIInterfaceOrientationLandscapeLeft == interfaceOrientation ) || ( UIInterfaceOrientationLandscapeRight == interfaceOrientation );
}
I stripped out those methods and put in the two above from Radoslava and all worked! The odd thing is that none of the ANE’s I’m using are instantiated during the initial app load or app launch sequence. So why they would have an effect on the application’s launch orientation is beyond me. The unfortunate reality is that it took a ton of time to debug this problem. I will chalk this one off as just being one of those strange Adobe/iOS issues. The good news is that with great people like Radoslava still working within the Adobe developer community, we are able to find fixes to problems like this. Thanks again for the help, and if anyone else experiences anything like this please don’t hesitate to get in touch with me, I need to pay my good fortune forward!