If I have read the accepted answer, I wouldn't have to write my own. My version is longer but only require app delegate's application(_:supportedInterfaceOrientationsFor:)
method. It maybe suitable in situation where you can't change or prefer not to change the target view controllers. For example, a third party view controller.
I was inspired from Apple's official doc: supportedInterfaceOrientations
My app runs as Portrait on iPhone and all orientations on iPad. I only want one view controller (a JTSImageViewController
presents an image for larger view) to be able to rotate.
Info.plist
Supported interface orientations = Portrait
Supported interface orientations (iPad) = Portrait, PortraitUpsideDown, LandscapeLeft, LandscapeRight
If app delegate implemented application(_:supportedInterfaceOrientationsFor:)
, Info.plist maybe ignored. However, I didn't verify that.
Swift 4
func application(_ application: UIApplication,
supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
// Early return for iPad
if UIDevice.current.userInterfaceIdiom == .pad {
return [.all]
}
// Search for the visible view controller
var vc = window?.rootViewController
// Dig through tab bar and navigation, regardless their order
while (vc is UITabBarController) || (vc is UINavigationController) {
if let c = vc as? UINavigationController {
vc = c.topViewController
} else if let c = vc as? UITabBarController {
vc = c.selectedViewController
}
}
// Look for model view controller
while (vc?.presentedViewController) != nil {
vc = vc!.presentedViewController
}
print("vc = " + (vc != nil ? String(describing: type(of: vc!)) : "nil"))
// Final check if it's our target class. Also make sure it isn't exiting.
// Otherwise, system will mistakenly rotate the presentingViewController.
if (vc is JTSImageViewController) && !(vc!.isBeingDismissed) {
return [.allButUpsideDown]
}
return [.portrait]
}