It's easy to not rotate on all screens, allow rotation on all screens, and not rotate only specific screens, but ** allow rotation on specific screens ** is quite annoying. This article will list several methods, so I think you should take the best method at any given time.
This is the most orthodox method. In the General settings
Check the box to allow rotation in the overall settings. After that, in all view controllers except the screen you want to rotate, allow only the vertical screen as follows.
override var supportedInterfaceOrientations: UIInterfaceOrientationMask { .portrait }
With the above steps, you can make only certain screens rotatable, but some challenges remain. First, it has a wide range of influence. If you are in the early stages of development, you may not care, but if you do this with a large existing application that already has dozens of screens, it is difficult because you have to check the behavior other than the screen you want to rotate. Also, when creating a new screen in the future, we must remember to allow only the vertical screen. If you have a common class like BaseViewController, you can specify it there and the changes will be small.
If you decline first, this method touches private properties and may not be available depending on the iOS version or may be rejected by the review. Method 1 will affect all screens that you do not want to rotate, but this method is completed only for the screen that you want to rotate.
First, implement the following within AppDelegate.
func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
if let rootViewController = UIApplication.getTopViewController() {
//Only HogeViewController allows rotation
if rootViewController is HogeViewController {
return .allButUpsideDown
}
}
//Other than that, only the vertical screen
return .portrait
}
Create a method to get the frontmost view controller used in the above code.
extension UIApplication {
///Get the view controller displayed at the top
static func getTopViewController(base: UIViewController? = UIApplication.shared.keyWindow?.rootViewController) -> UIViewController? {
if let nav = base as? UINavigationController {
return getTopViewController(base: nav.visibleViewController)
} else if let tab = base as? UITabBarController, let selected = tab.selectedViewController {
return getTopViewController(base: selected)
} else if let presented = base?.presentedViewController {
return getTopViewController(base: presented)
}
return base
}
}
By implementing the above, it is possible to allow rotation only on the target screen. However, with these alone, when transitioning to another screen during rotation, the other screen will also be displayed in a rotated state. Therefore, it is necessary to forcibly return the rotation of the screen at the time of transition as follows.
class HogeViewController {
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
if self.isMovingFromParentViewController {
UIDevice.current.setValue(Int(UIInterfaceOrientation.portrait.rawValue), forKey: "orientation")
}
}
}
ʻUIDevice.current.setValue (rotation direction, forKey: "orientation") `is a well-known technique for forcibly rotating, but it is not a legitimate method because it accesses private properties.
In method 2, the range of influence is smaller, but the process of returning the rotation is somewhat black magic. Therefore, the process of returning the rotation is performed on the transition destination screen. For example
FirstViewController -> HogeViewController -> FugaViewController
If such a transition can occur, you can explicitly specify the rotation direction with FirstVC and FugaVC.
class FirstViewController {
override var supportedInterfaceOrientations: UIInterfaceOrientationMask { .portrait }
}
class FugaViewController {
override var supportedInterfaceOrientations: UIInterfaceOrientationMask { .portrait }
}
However, when using this method, when a new wire is created from HogeVC and when a new wire is created to HogeVC, it is necessary to fix the rotation direction in the same way. Compared to method 1, the range of influence has decreased, but after all, it seems that future implementations need to be careful.
In mono's slide, it seems that it is implemented by the method using aspect orientation, and there seems to be various methods. After all, it is difficult to add rotation control later, so I think it is best to consider this area from the beginning if possible.
end
Recommended Posts