Where to put Navigation Controller in Interface Builder? - ios

Say, I have a Login screen, Contacts screen and Settings screen.
Login screen doesn't seem to be used frequently in the app so I suspect it is fine to exclude it from the main navigation flow.
Thus I set Login screen as the app entry point, then put all the rest screens as the children of the Navigation Controller. This way I do login process, then pass the control to the Navigation Controller and it does all the in-app navigation in a regular manner.
I am concerned if I am doing it right way, as probably I should make the Navigation Controller as the entry point and then dispatch all the navigation, even for Login screen, with it.
Is it supposed to have a single Navigation Controller inside an app? If so, is it supposed to have it as the parent dispatcher for all the scenes or is it fine to have some scenes put independent?
Here is the current config:

It's fine to embed multiple navigation controllers. In your case, I wouldn't think there would be any issues with not having the initial controller embedded in a nav controller-- getting back to the log in screen would be as simple as using an unwind segue. Alternatively, making the first VC a nav controller also presents no problem, but in your case it would eliminate the need for a second nav controller, based on your current configuration. I find multiple navigation controllers most useful when I'm using container views, and want to swap out VCs within that container.
That's my 2 cents.

Related

Navigation in SwiftUI - App Setup Navigation View flow into a Tab View Navigation flow

Picking up swift again for the first time in a while and this seems way more difficult than it should be to find a clear answer on the correct way to go about this as it seems like a common scenario for an app.
I need to present the user with a few set up screens (user registration, login, other details) that will only be presented once when first setting up the app.
When finished with this setup process the app should navigate to a Tab View based Home Screen which will be the main navigation throughout the app (with each tab item having its own NavigationView navigation)
Navigating from the setup to the home view with a Navigation Link stays within that initial navigation view hierarchy and I end up with double navigation bars on the Home Screen. I've also tried presenting the setup view as a FullScreenCover, but that didn't seem to fully work correctly either.
I'm avoiding posting code as I want to find the best way this will work for multiple projects, not specifically for what I'm currently working on.

Launching to a level other than root in UINavigationController, from a storyboard

Is it possible to launch an app to a specific level of a navigation stack using a storyboard?
I'm looking to recreate the model employed by Mail.app, where the app launches into the Inbox, but this is actually one level down the navigation stack, and tapping the back button takes you to the root...
I understand how this can be done via code, i.e. instantiating the navigation controller within the app delegate and then manually pushing the view controller(s) to create the desired stack, but I'd really like to know if there's a way to achieve the same using storyboards.
Unfortunately I don't think there is because you need to instantiate your navigation controller at some point that will house your view controllers, and if you do this through storyboards the best you can do is set the navigation controller to be the entry point.
However, it is pretty straightforward to do from code. If your navigation controller has two view controllers where ViewControllerOne pushes to ViewControllerTwo, then you can just can just push to the second one without an animation as follows:
navigationController.pushViewController(secondViewController, animated: false)
And the user will be one level deep in the navigation controller.

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

Benefits from using UiNavigationController

I am developing an iOS app that I have already developed for Android.
The problem is I don't know how to organize my UIViewControllers considering the following scheme of my app pages:
The scheme is simple: there is a login page which leads to the main page. From this main page, there are four buttons which all lead to a specific view hierarchy but at the very bottom of each, the user will be able to go back directly to the main page. Each page accessed by the main page will also have a custom back button (an image of my own)
The question is: is there any benefit in using a UINavigationController (obviously with the main page as its root) in my case? Or can I simply create each Controller and using only Modal Segues?
If your view controllers have a navigation relationship so using UINavigationController is the way to go:
In 'push' segue, you are basically pushing your ViewController into an
already setup "navigation stack". Well, of course, this is under the
assumption that the ViewController that performs the 'pushing'
operation belongs to the same navigation stack as the ViewController
is pushed into. Generally, you push a ViewController if the pushed
ViewController has some sort of a relationship with the pushing
ViewController. This is very common in applications that has a
NavigationController in its system. A good example for a push segue is
a system where you are displaying a list of contacts. And on tap of a
particular contact, you are pushing a VC that has the corresponding
details of the contact.
Example is real world: list of products => product details => product reviews
If you want to temporary present a view controller and the main focus is your view controller but you need to present another view controller to perform a task like "filter" , "login", adjust "settings" then modal segue is the way to go
In 'modal' segue, there is no stack as such. You are presenting a VC
'modally' over the presentee VC, if that makes sense. This can happen
across any ViewController without any relationship rules. The
presenter should take care of dismissing the VC it presented. A good
example for modal segue is login. On tap of login, you are modally
presenting a VC that has no relationship with the presenter.
If your view controllers are not related to each other, but each view controller has his own navigation stack then UITabBarController is the way to go
Storyboards (Xcode): What is the difference between a push and modal segue?
I would say if each of the additional view controllers from the main "home" view controller don't have any children view controllers, then you can just have each button present a view controller modally.
The main difference is if you are using a navigation controller, you can "pushing" a vc onto the navigation stack of view controllers, whereas presenting it modally can be thought of a "one time" action where the user does something on the new screen and has no where to advance to logically (like adding information to a new contact).
You can see this post for a more detailed answer:
What is the difference between Modal and Push segue in Storyboards?
Deciding whether to use a Modal segue vs a Show (push) depends entirely on purpose and context of the user's experience. If you are leading the user down a path which is linear, where each successive VC is diving deeper in to a singular idea, then use Show segues and NavigationControllers. Examples include, Settings app, where you can drill into all the specifics. Most e-commerce app will use a NavigationController to lead the user through a purchase.
If you want to present the user with a single concept, which the user can respond to, or close it to continue using the rest of the app. Then use a modal presentation. Adding a contact in the iPhone is a fine example of this.
Visually, the difference is that a Show segue presents the VC from the right side of the app, sliding onto the previous VC. (If the user has Arabic language turned on, a right to left language, the Show segue will come from the left hand side of the VC) A modal comes from the bottom of the app.
From looking at your drawing, but not know anything else about your app, I think you want to use NavigationControllers. You may also want to consider a TabBarController. If each of these buttons lead the user on various ways of using the app, like mini apps within one big one, then a TabBarController is appropriate.

How can I make one Tab Bar button refer to two views/controllers in iOS

I'm developing an iOS app just now with a Tab Bar navigation.
I have two screens which show the same information but in different formats (say, list and grid).
The two screens are different enough that they require separate controllers.
Users can toggle between the two views from a shared control bar button (toggle) at the top.
Scenario:
User presses the 'Places' button for the first time and it shows the places as a list.
They press 'grid' to see the same places displayed as a grid.
The user presses another tab bar button to navigate to a different screen.
When they press the "Places" button again, the app remembers their last viewed screen for places was the grid so the grid view is shown.
The user may then toggle back to list view. etc...
Can anybody recommend the best approach to achieving this?
One approach is to use one view controller that manages both views. That way, you don't have to bother with synchronizing data or subverting the normal function of UITabBarController -- there's just one controller. Also, don't try to overload the meaning of the tab for that controller. Instead, add a button to both views that tells the controller to switch to the other view. That'll be easier for your to build, and (more importantly) easier for the user to understand. It's not nice to make familiar controls do unfamiliar tricks.
If your view controllers are such that combining them into one would be complicated, then you can use two controllers and simply swap them in and out of the tab bar by modifying the tab bar controller's viewControllers array. You can still avoid having to sync data between them by having both controllers refer to the same data model.
I was trying to achieve this same thing, and it can actually be done with a basic setup of a TabBarController, NavigationControllers, ViewControllers, push segues, and unwinds.
TabBarController
|==> NavigationController --> PlacesController(grid view) --(push segue from nav bar)--> PlacesController(list view)
|==> NavigationController --> OtherController
|...
Make sure to have an unwind segue back from the list view controller to the grid view controller.
If you toggle between views then go to another tab (e.g. otherController) and come back, you'll return to the last view you were seeing because that's what is at the top of the stack of the NavigationController.

Resources