Rotation only in one ViewController
I'd recommend using supportedInterfaceOrientationsForWindow
in your appDelegate
to allow rotation only in that specific view controller, ex:
Swift 4/Swift 5
func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
// Make sure the root controller has been set
// (won't initially be set when the app is launched)
if let navigationController = self.window?.rootViewController as? UINavigationController {
// If the visible view controller is the
// view controller you'd like to rotate, allow
// that window to support all orientations
if navigationController.visibleViewController is SpecificViewController {
return UIInterfaceOrientationMask.all
}
// Else only allow the window to support portrait orientation
else {
return UIInterfaceOrientationMask.portrait
}
}
// If the root view controller hasn't been set yet, just
// return anything
return UIInterfaceOrientationMask.portrait
}
Note that if that SpecificViewController
is in landscape before going to a portrait screen, the other view will still open in landscape. To circumvent this, I'd recommend disallowing transitions while that view is in landscape.
Swift 3
func application(application: UIApplication, supportedInterfaceOrientationsForWindow window: UIWindow?) -> Int {
// Make sure the root controller has been set
// (won't initially be set when the app is launched)
if let navigationController = self.window?.rootViewController as? UINavigationController {
// If the visible view controller is the
// view controller you'd like to rotate, allow
// that window to support all orientations
if navigationController.visibleViewController is SpecificViewController {
return Int(UIInterfaceOrientationMask.All.rawValue)
}
// Else only allow the window to support portrait orientation
else {
return Int(UIInterfaceOrientationMask.Portrait.rawValue)
}
}
// If the root view controller hasn't been set yet, just
// return anything
return Int(UIInterfaceOrientationMask.Portrait.rawValue)
}
You can also do it in a protocol oriented way. Just create the protocol
protocol CanRotate {
}
Add the the same 2 methods in the AppDelegate in a more "swifty" way
func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
if topViewController(in: window?.rootViewController) is CanRotate {
return .allButUpsideDown
} else {
return .portrait
}
}
func topViewController(in rootViewController: UIViewController?) -> UIViewController? {
guard let rootViewController = rootViewController else {
return nil
}
if let tabBarController = rootViewController as? UITabBarController {
return topViewController(in: tabBarController.selectedViewController)
} else if let navigationController = rootViewController as? UINavigationController {
return topViewController(in: navigationController.visibleViewController)
} else if let presentedViewController = rootViewController.presentedViewController {
return topViewController(in: presentedViewController)
}
return rootViewController
}
And in every ViewController that you want a different behaviour, just add the protocol name in the definition of the class.
class ViewController: UIViewController, CanRotate {}
If you want any particular combination, they you can add to the protocol a variable to override
protocol CanRotate {
var supportedInterfaceOrientations: UIInterfaceOrientationMask
}