Custom Orientations on a specific view controller - ios

I have many view controllers in my app (which supports all orientations). Some of those view controllers have content that is too much to fit in landscape. How can I limit some of my views to portrait while also having some portrait and landscape.
P.S. I'm using objective-C, and i've seen a lot of swift answers but I'm not good at translating Swift->Obj-C

It depends on how your view controller hierarchy is set up.
For example, if you have a UINavigationController as your window's rootViewController, you can have a UINavigationControllerDelegate which returns the navigation controller's topViewController.supportedInterfaceOrientations. Then in your portrait-only view controllers, you would return UIInterfaceOrientationMaskPotrait in supportedInterfaceOrientations, and UIInterfaceOrientationMaskAll in the rest of your view controllers.
See here: https://stackoverflow.com/a/27623947/1812788

Related

iOS Custom modal presentation ignores supportedInterfaceOrientation

I'm currently using a custom subclass of UIViewControllerTransitioningDelegateto create a custom modal presentation. The problem I'm facing is when the presenting and presented view controllers support different interface orientations.
My situation is pretty simple. View Controller A supports all orientations. View Controller B only supports portrait. When A presents B while in landscape, B is presented in landscape.
This behavior can be fixed by switching from a custom modal presentation to a default presentation, which would imply that there is a way for the transitioning delegate to fix this behavior without some of the hacks that have been accepted on other answers.
What is the correct way of supporting different view controller orientations when creating custom modal animations?

popViewControllerAnimated: From Landscape To Portrait

I'm having trouble popping a UINavigationController (subclass) from a landscape view to a portrait view.
I have a chain set up from the window's rootViewController using shouldAutorotate and supportedInterfaceOrientations down to the individual View Controllers that I present.
So, I have a View Controller that ONLY supports portrait. The next one that is pushed supports landscape as well.
When I push the one that supports landscape and then rotate the device, everything rotates. So far, so good.
Now, when I pop back to the first one, both views rotate BEFORE the animation. So, the second viewController's landscape view (which is really small because of the rotation transform) is pushed away to the right side of the portrait screen.
I want the landscape view to be pushed away to its right (the top or bottom of the portrait view controller), while the portrait view controller is shown in the background.
How can I accomplish this?
I thought I might try to use an animation controller, but the UINavigationController's delegate method, navigationController:animationControllerForOperation: isn't called when popping to a View Controller in a different orientation.
After days of experimentation I figured out what my problem was. Hopefully this will help someone in the future.
I was trying to over-engineer the chain.
I had a custom container with a child tab bar controller which contained multiple navigation controllers that contained view controllers with different orientation requirements.
My main downfall was assuming that even if a modal window was presented, the system would still ask the window's root view controller first. To account for this situation I added a check in the container that looked like this:
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
if (self.presentedViewController) { // This check is wrong! Don't do this!
return [self.presentedViewController supportedInterfaceOrientations];
}
// Pass request to child view controller
}
However, this was fundamentally causing my problem in two ways.
First, without this check, UIKit will automatically detect the modal view controller and directly ask for its supportedInterfaceOrientations.
Second, the way UIKit handles the animations involves presenting several internal view controllers that we normally would have no idea are there. By checking for a modal view controller in presentingViewController, the check was catching them and asking them all for their supportedInterfaceOrientations. UIKit isn't meant to behave this way, so I was the one interfering with its operations.
The fix was to implement supportedInterfaceOrientations so that it ONLY concerns the view controller's direct descendants (i.e. the view controllers whose views are descendants in the current view controller's view hierarchy). The direct descendants can further pass the request down from there.
Treat modal windows as a completely separate chain, regardless of the presenter.
In other words, trust UIKit.

How to restrict single UIViewController in iOS 10 universal app to portrait layout?

I have an iOS 10 universal app (supports both iPad and iPhone). In the application .plist I have specified that the app supports both portrait and landscape mode. Now I would like to restrict a single UIViewController to portrait only mode. That view controller is presented by the same navigation controller that presents other view controllers. What is the best (easiest) way to restrict a single, specific view controller to portrait in iOS 10. (Note that there are lots of published solutions, but as far as I can tell the answer to this problem is is different for different versions of iOS. I only need a solution that supports iOS 10.)
Now I would like to restrict a single UIViewController to portrait only mode. That view controller is presented by the same navigation controller that presents other view controllers
In iOS 10, there is no supported way to do what you're describing. A navigation controller cannot have some of its children in one orientation and other children in another.
The only supported way to have a view controller force a different orientation is to make it a presented view controller (modal), not a pushed view controller in a navigation controller stack.

Disabling rotation for ViewController in NavigationController

Is it even possible to disable rotation when the View Controller I want to disable it in is
in a Navigation Controller that supports all directions? for one special view I want only portrait mode to be allowed, I´v tried about everything but nothing seems to work - I am guessing this is cause the View Controller is part of a Navigation Controller with segues?
By Default any property or a setting of a Super View is applied on all the sub-views inside it. Therefore even if you block the View Controller it will rotate because it is in Navigation Controller that allows rotation. Therefore i would suggest that you create a property in your AppDelegate that sets the orientation settings and then haldle it from ViewControllers

UISplitViewController - willShowViewController Not Firing

I am converting an iPhone application to work on the iPad. In this case, the user interface was created with interface builder. The interface of the root controller (at index 0), consists of a Tab Controller & Navigation Controllers in this layout:
Tab Controller
Navigation Controller 1
Navigation Controller 2
Navigation Controller 3
I have been implementing this in pieces. When I setup the Tab Controller & Navigation Controller 1 as a first step, everything works correctly. willHideViewController & willShowViewController work correctly. My interface switches from SplitView to Popover correctly. When I add Navigation Controller 2, willHideViewController & willShowViewController never fire & I always see the Popover controller no matter what orientation the iPad is within the simulator.
When I add a second navigation controller, is there something else I need to tie off within the interface builder to get the interface to work correctly?
I'm guessing that you've set a delegate for the first navigation controller but not one for the second. The delegate object would receive methods like willHideViewController.
I'm also not sure that having multiple navigation controllers is good style. A view controller knows that it has been placed in a navigation controller, and you can access this with self.navigationController. You should keep pushing view controllers on the same navigation controller. Or I may have misunderstood what you're trying to do with your tab controller.
The answer to this is pretty simple: When you implement the split view controller & you want everything to switch correctly from portrait to landscape, you need to make sure that all the interface elements implement shouldAutorotateToInterfaceOrientation for portrait & landscape layouts.

Resources