will you please give your thoughts (code review) on these two way of solving orientation.
About the app:
We have a universal App. The main purpose of the app is to watch the videos. The app has four screens.
- Shows the list of shows
- show the list of episodes in the show
- details of an episode
- Player screen
The way we implemented is
- a navigationalViewController that shows the viewController 1 (list of show)
- then drill into viewController 2 (episodes of a show)
- then drill into viewController 3 (episode details)
- then viewController 4 ( with av media player view) presented modally from viewController 3
Requirement of orientation:
+--------+------------------+---------------------+-----------------------+-----------------------------+
| Device | Shows list (vc1) | Episodes list (vc2) | Episode details (vc3) | Player ViewController (vc4) |
+--------+------------------+---------------------+-----------------------+-----------------------------+
| iPad | Landscape | Landscape | Landscape | Landscape |
+--------+------------------+---------------------+-----------------------+-----------------------------+
| iPhone | Portrait | Portrait | Portrait | Portrait & Landscape |
+--------+------------------+---------------------+-----------------------+-----------------------------+
Method 1:
Implement this following code at app delegate level
func application(_ application: UIApplication,
supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
guard let viewController = self.window?.rootViewController?.presentedViewController else {
if UIDevice.current.userInterfaceIdiom == .pad {
return .landscape
}
return [.portrait, .portraitUpsideDown]
}
if viewController is PlayerViewController && viewController.isBeingDismissed == false {
return .all
} else {
if UIDevice.current.userInterfaceIdiom == .pad {
return .landscape
}
return [.portrait, .portraitUpsideDown]
}
}
Method 2:
Implement this following code at navigationViewController level
class MyNavigaitonViewController: UINavigationController {
override var shouldAutorotate: Bool {
if self.traitCollection.userInterfaceIdiom == .pad {
return true // we are supporting both landscapeLeft and landscapeRight on iPad.
}
return false }
override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
if self.traitCollection.userInterfaceIdiom == .pad {
return .landscape // we are supporting both landscapeLeft and landscapeRight on iPad.
}
return .portrait }
}
Player view controller has this following code in both Method 1 and Method 2
extension PlayerViewController {
override var shouldAutorotate: Bool {
if self.traitCollection.userInterfaceIdiom == .pad {
return true // we are supporting both landscapeLeft and landscapeRight on iPad.
}
// TODO: workout a way to support landscapeleft & right in phone
return true
}
override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
return UIInterfaceOrientationMask.all
}
}
2 Answers 2
What about implementing CoreViewController class which by default support landscape for iPad and portrait for iPhone. All your VCs inherit from it. As a result VC1,VC2 and VC3 will have it by default and in VC4 override rotation methods to add support for landscape mode?
I recommend to use default Apple-provided ways to implement this logic. You can use the delegate method to force your UINavigationController to use it's visibleViewController
to determine the orientation. The visibleViewController
is a wonderful property which will return modal vc if it's presented or top vc otherwise.
func navigationControllerSupportedInterfaceOrientations(_ navigationController: UINavigationController) -> UIInterfaceOrientationMask {
return navigationController.visibleViewController?.supportedInterfaceOrientations ?? .all
}
Then override supportedInterfaceOrientations
of all view controllers. This will be most flexible and portable solution.
If you want all-in-one-place solution you should use something like your Method 1.
viewController.isBeingDismissed == false
condition? \$\endgroup\$