I have a simple app consisting of a single view controller. I started with the Xcode 7 GM Single View Application template, but then deleted the main storyboard, and set up my view controller like this:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
let vc = ViewController()
window = UIWindow(frame: UIScreen.mainScreen().bounds)
window!.rootViewController = vc
window!.makeKeyAndVisible()
return true
}
In my info plist, I have all orientations specified under Supported Interface Orientations, and the app rotates to all orientations on iPad.
However, in my simple¹ view controller, the shouldAutorotate()
and supportedInterfaceOrientations()
methods are never called. This is a problem, because I'm experimenting with a UI control enabling and disabling auto rotation. What could be preventing these methods from being called?
Sample project here (requires Swift 2)
¹non-UINavigationController
According to this post on the Apple Developer forum, if you have iPad multitasking enabled (new in iOS 9), you can no longer control the orientations you support:
https://forums.developer.apple.com/message/13508#13508
You can add a counter rotation, but it's not pretty, at least as far as I can tell. I got it working, but was unable to disable the animation of the corners when you rotate so you get this weird looking situation where it looks like it's rotating, but the content doesn't rotate.
Here is the code I was using to counter the rotation. Note that I had to hide the status bar too or it would rotate as well and I couldn't figure out how to counter that.
Also note that doing the auto rotation on self.navigationController.view.superview.superview
is likely not the best way and may break at some point in the future. There is likely a better way to get the correct view used to counter the rotation. Obviously if you aren't using a navigation controller, you would need to pass in a different view. YMMV.
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[[UIApplication sharedApplication] setStatusBarHidden:YES];
self.startingInterfaceOrientation = [[UIApplication sharedApplication] statusBarOrientation];
}
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
[super willAnimateRotationToInterfaceOrientation:toInterfaceOrientation duration:duration];
[self updateLayoutsForCurrentOrientation:toInterfaceOrientation view:self.navigationController.view.superview.superview];
}
- (void)updateLayoutsForCurrentOrientation:(UIInterfaceOrientation)toInterfaceOrientation view:(UIView *)view {
CGAffineTransform transform = CGAffineTransformIdentity;
if (self.startingInterfaceOrientation == UIInterfaceOrientationPortrait) {
switch (toInterfaceOrientation) {
case UIInterfaceOrientationLandscapeLeft:
transform = CGAffineTransformMakeRotation(M_PI/2.0f);
break;
case UIInterfaceOrientationLandscapeRight:
transform = CGAffineTransformMakeRotation(-M_PI/2.0f);
break;
case UIInterfaceOrientationPortrait:
transform = CGAffineTransformIdentity;
break;
case UIInterfaceOrientationPortraitUpsideDown:
transform = CGAffineTransformMakeRotation(M_PI);
break;
default:
break;
}
}
else if (self.startingInterfaceOrientation == UIInterfaceOrientationPortraitUpsideDown) {
switch (toInterfaceOrientation) {
case UIInterfaceOrientationLandscapeLeft:
transform = CGAffineTransformMakeRotation(-M_PI/2.0f);
break;
case UIInterfaceOrientationLandscapeRight:
transform = CGAffineTransformMakeRotation(M_PI/2.0f);
break;
case UIInterfaceOrientationPortrait:
transform = CGAffineTransformMakeRotation(M_PI);
break;
case UIInterfaceOrientationPortraitUpsideDown:
transform = CGAffineTransformIdentity;
break;
default:
break;
}
}
else if (self.startingInterfaceOrientation == UIInterfaceOrientationLandscapeLeft) {
switch (toInterfaceOrientation) {
case UIInterfaceOrientationLandscapeLeft:
transform = CGAffineTransformIdentity;
break;
case UIInterfaceOrientationLandscapeRight:
transform = CGAffineTransformMakeRotation(M_PI);
break;
case UIInterfaceOrientationPortrait:
transform = CGAffineTransformMakeRotation(-M_PI/2.0f);
break;
case UIInterfaceOrientationPortraitUpsideDown:
transform = CGAffineTransformMakeRotation(M_PI/2.0f);
break;
default:
break;
}
}
else if (self.startingInterfaceOrientation == UIInterfaceOrientationLandscapeRight) {
switch (toInterfaceOrientation) {
case UIInterfaceOrientationLandscapeLeft:
transform = CGAffineTransformMakeRotation(M_PI);
break;
case UIInterfaceOrientationLandscapeRight:
transform = CGAffineTransformIdentity;
break;
case UIInterfaceOrientationPortrait:
transform = CGAffineTransformMakeRotation(M_PI/2.0f);
break;
case UIInterfaceOrientationPortraitUpsideDown:
transform = CGAffineTransformMakeRotation(-M_PI/2.0f);
break;
default:
break;
}
}
view.transform = transform;
}
Much of this code was adapted from Jared Sinclair's JTSImageViewController (posted with his permission), available under the MIT license on github here: https://github.com/jaredsinclair/JTSImageViewController
To opt out of being eligible to participate in Slide Over and Split View, add the UIRequiresFullScreen key to your Xcode project’s Info.plist file and apply the Boolean value YES.
I just tried the solution in this thread:
https://stackoverflow.com/a/32782517/1679627
Note that there are two entries in the info.plist one for supported orientations on iPhone and one for iPad.