Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to prevent rotation on iOS 11?

As of iOS 11.2 I notice that (BOOL)shouldAutorotate, (BOOL)shouldAutorotateToInterfaceOrientation, (UIInterfaceOrientationMask)supportedInterfaceOrientations etc. are no longer called.

How do I prevent rotation to a certain orientation now?

I can switch off rotation on the Deployment level of the target, but what I actually want it to switch off rotation just for the iPhone X. I have an older app without storyboards, and don't want to change the app to honour the silly notch in the screen in landscape mode.

Landscape IS useful in my App, as on iPhone you get a wider keyboard in landscape mode, which is nice. Else I'll just remove rotation for all iPhone models..

It is in the documentation for UIViewController:

"As of iOS 8, all rotation-related methods are deprecated. Instead, rotations are treated as a change in the size of the view controller’s view and are therefore reported using..."

and:

"You can override the preferredInterfaceOrientationForPresentation.."

but that is not called either. Not in the root view controller, nor in other viewcontrollers.

So, how do I prevent rotation to a certain orientation now, programmatically?

like image 835
RickJansen Avatar asked Jan 28 '23 15:01

RickJansen


1 Answers

As mentioned in documentation

A view controller can override the supportedInterfaceOrientations method to limit the list of supported orientations.

So we need to override shouldAutorotate and supportedInterfaceOrientation to target view controllers.

Typically, the system calls this method only on the root view controller of the window or a view controller presented to fill the entire screen.

This will work if you have very simple configuration like your target view controller is the rootViewController of window or being presented covering whole screen.

But when you have other configuration like your target view controller is embedded in some other container view controller like UINavigationController or UITabBarController, so now application's window will only ask its rootViewController (now container view controller) for supportedInterfaceOrientation.

Now further reading the documentation,

child view controllers use the portion of the window provided for them by their parent view controller and no longer participate directly in decisions about what rotations are supported.

So may be default implementation of these container view controllers not asking there children for there supportedInterfaceOrientation preference.

So to allow our target child view controller to specify there supportedIntefaceOrientation we need to tell there container view controller to do so.

In case of UINavigationController

extension UINavigationController {
  open override var shouldAutorotate: Bool {
    return true
  }

  open override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
      return topViewController?.supportedInterfaceOrientations ?? .allButUpsideDown
  }
}

And in case or UITabBarController

extension UITabBarController {
  open override var shouldAutorotate: Bool {
      return true
  }

  open override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
      return selectedViewController?.supportedInterfaceOrientations ?? .allButUpsideDown
  }
}

EDIT

To implement proper rotation behaviour in your view controllers, you should subclass these ContainerViewController (UINavigationController, UITabBarController, UISplitViewController etc) and then override these properties, because extending these UIKit Classes globally will cause unexpected behavior as mentioned in Customizing Existing Classes.

If the name of a method declared in a category is the same as a method in the original class, or a method in another category on the same class (or even a superclass), the behavior is undefined as to which method implementation is used at runtime. This is less likely to be an issue if you’re using categories with your own classes, but can cause problems when using categories to add methods to standard Cocoa or Cocoa Touch classes.

like image 188
Ratnesh Jain Avatar answered Mar 19 '23 12:03

Ratnesh Jain