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

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.

Related

Transition between different presentation styles for a UIViewController using swift

I'm trying to create an affect where I present a UIViewController as a popover and then animate that view controller into a few different modal presentation styles.
I have successfully presented the view as a popover, and then after dismissing the view re presented it as a full screen overlay but I'm having trouble finding a workflow that allows me to transition without first dismissing the view controller.
I've included an illustration below showing the kind of effect I'd like to achieve where a single view controller transitions between 3 presentation styles, A, B, & C without being dismissed.
In the illustration A represents a popover modal presentation style, B custom, and C fullScreen
It's worth noting that these particular modal presentation styles are not important, rather that I would like to be able to transition between many kind of modal presentation style for a single view controller without first dismissing it.
What would be the best way to approach this kind of transition?

Swift Full Screen Navigation Push Segue

I want to achieve something similar to Facebook's way of presenting the comments view controller for a specific post. In below picture one can see, that the pushed new view controller is presented "full screen" (for the lack of a better way of describing the behaviour). It seems to me like some kind of modal segue rather than a push one. When trying to recreate that in my own app I can't achieve that the whole navigation bar is included in the presentation segue. Only the view inside the presentation hierarchy is changed. I want the second view controller to be entirely white (the view as well as the navigation bar) but both view controllers should have the default swipe-to-go-back behaviour. How can that be done?
What they're probably doing is hiding the navigation bar.
You can achieve the same effect if you set navigationController?.navigationBar.isHidden = true (can also do it on navigation bar in UINavigationController from the storyboard), make a regular show segue and just display it using performSegue(withIdentifier: "nextScreen", sender: nil). You can then make your own UI logic for displaying back buttons etc.

How to Share a View Across a Navigation Hierarchy with No Animation?

I have a simple Navigation View Hierarchy that has 2 views it goes between. I wanted a customized navigation bar, so I have the default one hidden, and I've implemented a Container View which is shared between the 2 views in the nav hierarchy.
Everything works as I want it to, except when I segue to the lower or higher view the top bar appears slides away and reappears on the new view. I would like it to appear stationary when I push or pop to other views in the hierarchy.
Is there an easy way to do this? Or should I delete my custom shared Container View and try to make this work with the Navigation Bar (which I have currently "hidden")?
I had to do this for a client once. The way we did it was, like you said, make an encompassing view controller that housed a container view. Within this container view, we embedded a UINavigationController and would manually pop and push UIViewControllers to its navigation stack. Of course you want to hide the UINavigationController's nav bar.
It sounds like you sort of implemented this, but instead you just embedded a plain old view controller inside your custom navigation controller, and then segue to another view controller that is also embedded in the custom view controller? Ideally you want one instance of this custom nav controller with an embedded UINavigationController. I believe you will have to do all the view controller transitions programmatically.
Opinion: Personally, I would recommend against doing this. I believe that an app should feel like an extension of the OS it's on. A user should feel it's a part of their phone. Using the native navigation bar also decreases the level of effort a user is required to put forth to understand your app.
I know you're thinking "but it's just a nav bar" but we're talking about the same people that will potentially uninstall an app if it takes longer than 2.5s to load.
I wanted a customized navigation bar, so I have the default one hidden
That's your mistake. The way to get a customized navigation bar in a UINavigationController interface is to initialize it with init(navigationBarClass:toolbarClass:). Now the built-in navigation controller is using your navigation bar! And from there on, all will be well.
https://developer.apple.com/reference/uikit/uinavigationcontroller/1621866-init

Objective-C - Understanding view controllers

I understand that view controllers help control multiple views in an application, but I have trouble understanding when to use them.
If I have an application with a main page, several views with a "hierarchy" structure, and an about page not connected with the hierarchy, what files should my application have? An appdelegate, navigation controller and view controller? More than one view controller? Just a navigation controller?
Also, should they all be contained in one .xib file, or multiple .xib files?
Any help would be greatly appreciated.
Thanks.
A good habit is to have a UIViewController for each page you want to show. If I get the structure of your app you should have a main page (with many other UIViews inside it) and another page (about page). If that's true I suggest two UIViewControllers.
The UINavigationController is a subclass of UIViewController that lets you "navigate" among the pages. It's not strictly necessary but suggested (you can also implement your self a custom navigation system, but it's easier to exploit the one Apple offers you). Another navigation system is the one based on UITabBarController, if you want to take a look.
Assuming I get the structure of your app you should need two .xib file, one for each page you have.
The app delegate is conceptually different from a view controller, you'll have just a single app delegate, automatically created by Xcode (you can, of course, modify it to fit your needs).
Each "screenful of content" (Apple uses this term) should be handled by it's UIViewController or more likely a subclass of it. The point of view controller is to handle view appearing or disappearing (going on/offscreen), device rotation, memory management, navigating to other view controllers and so on. If you are creating your UI with IB, then each of those view controllers would most likely have it's own .xib file.
Each view controller has one view (it's view property) that acts as main view for each "screenful of content" to which you then add your subviews.
UINavigationController and UITabBarcontroller are there to help you control the hierarchy of your app. They only act as containers for other view controllers and don't contain any UI except navigation bar or tab bar. Using tab bar controller you can have multiple view controllers which act exactly like browser tabs. Using navigation controller you can have a stack-like navigation where new view controllers are pushed from right to left and are popped from left to right when user goes back to previous view controller. You can even have a view controller inside navigation controller inside a tab bar controller.
If you don't want to use tab bar or navigation controller, you can navigate through your view controllers by presenting them modally using presentModalViewController:animated: and dismissing by dismissModalViewControllerAnimated:. If you send YES for animated parameter of these methods, you will get an animation specified by the modalTransitionStyle property of view controller being presented or dismissed. Possible animations are slide in from bottom (default), horizontal flip of entire screen, fade in/out and half-page curl.
There are also some Apple-provided subclasses of UIViewController that help you setup your UI quicker like UITableViewController which is basically a view controller that contains a table as it's main view and conforms to 'UITableViewdataSourceanddelegate` protocols which are required to define how each cell looks and what it contains.
On iPad there is one additional container controller UISplitViewController and one additional way to present new view controllers using UIPopover.

Can a UISplitViewController be the root controller in a UINavigationController?

Interface builder does not allow you to add a UISplitViewController as the root controller of a UINavigationController.
I've also tried programmatically creating the UINavigationController and setting its root view controller to be the UISplitViewController.
The result is an empty window with just the nav bar.
I've also tried a split view controller replacement, MGSplitViewController. It mostly works, except that within the split view controller, the master view is another UINavigationController. Its nav bar shows up too thick. Changing orientation and back clears it up.
I've been trying all sorts of different approaches to having a view that looks like a split view and other views that I switch between. I've tried within a tab view controller, writing my own controller to manage subviews of the window and having the split view as a managed view, and now the navigation controller. All attempts have had some issues. The most consistent issue is regarding the orientation of the view. My app is running in landscape mode and typically the child views think its still portrait.
Any ideas appreciated.
No.
The bottom line: a UISplitViewController must be the root view of an app (or perhaps more specifically, a window). It can not live inside a UINavigationController or anything else.
This is the case with the current SDK, and there's no guarantee that will change in future SDKs.
It seems strange to add a split view to a navigation stack. The master pane of a split view controller is generally a navigation controller, so (without knowing more about your design), I'd probably use that to control your navigation hierarchy.

Resources