iOS Custom modal presentation ignores supportedInterfaceOrientation - ios

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?

Related

With a custom navigation controller push transition, how do I have the previous view controller behind like modal presentations?

When performing a custom modal view controller transition, the view controller you're coming from sits behind the new one nicely (think of Apple's "form sheet" style presentation on an iPad for instance), and when you rotate the device the previous view controller visible in the back rotates as well.
I'm unsure how to get this functionality with a UINavigationController custom push animation. It seems it isn't expected for the previous view controller to be visible from behind and it isn't.
I could take a screenshot, but it won't update on landscape rotation.
How is it done so easily with a modal transition and how do I replicate that for navigation controller custom transitions?
As far as I understand the UINavigationController class such functionality cannot be achieved through it.
UINavigationController is a container controller, which can show only one VC within it at a time. It keeps all the VCs in the stack, but not their views (views are kept by VCs themselves).
Unlike it, the modal presentation is a special type of VC-presentation, and it's not limited by the container-functionality.

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.

Custom Orientations on a specific view controller

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

Can I move from a login View to a SplitView in an iPad application?

Hope there is not an answer yet (I've checked). Can I introduce a login View in my application that enables a SplitView by using a button or something?
I've checked MGSplitViewController, but I'd like to use something more light and minimal.
If it's not possible, can I introduce a login View in my DetaiView that enables a TableView?
You can transition between arbitrary view controllers in iOS. The usual ways are using modal presentation (I like to present splash screens with a cross-dissolve animation to the root view controller of the app), or pushing/popping with navigation controllers. You can also programatically swap between multiple views in a view controller via setting the "view" property.

Resources