I want some of my ViewControllers landscape and some portrait so this is what I did:
I enabled landscape mode:
Next I added these lines of code to the view controllers I wanted to be Portrait:
-(NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationPortrait;
}
-(BOOL)shouldAutorotate
{
return NO;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
return UIInterfaceOrientationPortrait;
}
However when I rotate them they still go to landscape mode.How can I fix that?
Here is how I do it.
Make a UINavigationController parent class.
inside you UINavigationController (parent) override these methods like:
- (NSUInteger)supportedInterfaceOrientations
{
if([self.topViewController respondsToSelector:@selector(supportedInterfaceOrientationsForThisContorller)])
{
return(NSInteger)[self.topViewController performSelector:@selector(supportedInterfaceOrientationsForThisContorller) withObject:nil];
}
return UIInterfaceOrientationPortrait;
}
- (BOOL)shouldAutorotate
{
if([self.visibleViewController respondsToSelector:@selector(shouldAutorotateNow)])
{
BOOL autoRotate = (BOOL)[self.visibleViewController
performSelector:@selector(shouldAutorotateNow)
withObject:nil];
return autoRotate;
}
return NO;
}
Now your NavigationController should be a subclass of the UINavigationContorller parent
Swift 3:
Inside your UINavigationController subclass do this
override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
get {
return self.topViewController?.supportedInterfaceOrientations ?? .all
}
}
override var shouldAutorotate: Bool {
return self.topViewController?.shouldAutorotate ?? false
}
Update
Taken from Matt's answer if you don't want to subclass:
first: make your viewController a delegate of the navigationController in viewDidLoad
self.navigationController?.delegate = self
Then declare UIViewController extension to respond to the delegate method as shown below:
extension UIViewController: UINavigationControllerDelegate {
public func navigationControllerSupportedInterfaceOrientations(_ navigationController: UINavigationController) -> UIInterfaceOrientationMask {
return navigationController.topViewController?.supportedInterfaceOrientations
}
}
The Apple designed way to do this for UINavigationController
is via UINavigationControllerDelegate
.
Usually I just update this delegate to do the following and delegate it to the top displaying controller in the navigation controller's stack:
#pragma mark - UINavigationControllerDelegate
- (NSUInteger)navigationControllerSupportedInterfaceOrientations:(UINavigationController *)navigationController
{
return [navigationController.topViewController supportedInterfaceOrientations];
}
In my opinion the UINavigationController
should just default to the above behavior but this is the api Apple has provided :)
As for the info plist file I uncheck all of the options and handle it all in code as it has caused issues for me in the past and I got tired of dealing with it.
Just for you all information,
create a new project single view based Application,
implement the should auto rotate delegate and the supportedInterface orientation in viewController
add breakpoint in it.
The run (universal mode)
- on iphone simulator : execution stops at breakpoints
- on ipad Simulator : executions DOESN'T STOP (delegate methods are never called !!!!)
- on ipad device : ok
So don't waste too mush time on it like I juste Did, XCode 7.3 is BUGGED
You can see the answer in the following post:
iOS 6 rotations: supportedInterfaceOrientations doesn´t work?
Let me know if it's your problem.
When under UINavigationController, I'm implementing the UINavigationControllerDelegate and the following method:
#pragma mark - From UINavigationControllerDelegate
-(UIInterfaceOrientationMask) navigationControllerSupportedInterfaceOrientations:(UINavigationController*)navigationController {
return UIInterfaceOrientationMaskPortrait; // TODO: change to whatever you need to allow
}