I’d like to have split views in several places of my iOS app, none of them as the root view controller. I understand that split views are initially designed to sit at the root of the app and provide the root navigation controller, and that Apple’s guidelines initially did not allow any workarounds. Updated guidelines state
You cannot push a split view controller onto a navigation stack. Although it is possible to install a split view controller as a child in some other container view controllers, doing is not recommended in most cases.
Now the split view pattern would really benefit my app, and I don’t want to reinvent the wheel here, so I gave it a try using a container view, mainly using the following steps:
Create a scene with a regular UIViewController.
Add a UIContainerView covering the entire screen.
Add a UISplitViewController to the storyboard, which creates a split view controller, a navigation controller, a table view controller (for the master view), and a regular view controller (for the detail view).
Create an embed segue from the container view to the split view controller.
This has a few quirks, which I hope to iron out eventually (e.g. initially showing detail view, swiping in the table view from the left on an iPad apparently tries to also back nav on the main navigation), but it basically works. So far, so good.
Now, the problem is that I have two navigation controllers: the main navigation controller at the root of my app and the navigation controller in the embedded split view. This gives me two navigation bars with independent navigation, allowing me to:
navigate back to the root of the split view using the embedded navigation controller
navigate back from the container view in the enclosing navigation controller
Besides two navigation bars not being appealing, I don’t want iPhone users to perform the second directly from the detail view. So my next steps were:
hide the navigation bar in the outer view controller
add a back navigation button to the inner navigation bar to take over the role of the main navigation bar’s back button
Left to do is the implementation for that back button that pops the container's view controller of the main navigation stack. The question is: how can I access the main navigation controller from the embedded view that has its own navigation controller (using Swift)?
Accessing the navigation stack of the parent's (containing view controller's) navigation controller turned out to be straightforward:
#IBAction func backButtonTapped(_ sender: UIBarButtonItem) {
parent?.navigationController?.popViewController(animated: true)
}
I had to face a similar kind of problem while developing my app.
My problem was, I had to display navigation controller and splitviewcontroller on side bar. Again a problem was navigation controller form splitview to navigation controller. Below are the steps which i followed
1) While creating a split view controller, I hided the navigation controller of master and detail and set it to root view, please also keep the reference of your top level navigation controller.
2) I increased the 'y' of splitview.root.window and view to accommodate custom view.
3) I created a custom view with a back button and then handled the transition with animation.
Please let me know if you want code snippets. I would have shared it now. But i have to search for it.
Related
I am creating an app using UItabBarController. I have 5 tabBar items at the bottom.
should I wrap navigationController in each item? Is that the best practice, and if not what's the best practice?
The tabs in a UITabBarController represent independent sections within an app. An example is Apple's Clock app. It has 4 tabs which are completely independent of each other.
A navigation controller represents a top-down hierarchy / stack of view controllers (meaning you start with a root view controller and then 'push' view controllers onto the stack. This almost inevitably means that it shows a 'logical flow'. You perform an action like selecting something on a view controller, which takes you into a more detailed view related to the action you performed. An example is Apple's Notes app which shows a list of folders of notes, selecting a folder pushes the screen with the list of notes in that folder onto the navigation stack, selecting a note in that list pushes the note that the user tapped on, onto the top of the list of notes.
Generally you should have tab bar controller as your app's root view controller and then each of the tabs could have a navigation controller as its root. It wouldn't usually have a tab-bar inside a navigation controller.
One case where a tab-bar could live inside a navigation controller is when a tabbed interface is presented modally.
To your question "should I wrap navigationController in each item", I think yes each tab should have a navigation controller as the root if a navigation hierarchy is required in that tab.
Hope this helps you.
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
I'm still struggling with navigation bars and just can't work out how to edit or verify that I have a navigation bar on my view and I would appreciate any help.
I have a project with another set of scenes similarly comprising of a navigation controller and three associated view controllers (connected via segues and main table view embedded in the navigation controller) and I was able to add a navigation bar manually in interface builder to the outer view controllers that were segued to the table view controller.
But in this set of scenes the navigation controller is set up as the root view controller for the table view.
I have another set of scenes. A navigation controller and two related view controllers - both table view controllers. I embedded the first table view controller in the navigation controller and I then added a second table view controller to this (for a new screen I want to add to my app) and I connected this second table view controller to my first table view controller by way of a show segue (just like I did yesterday with other set of scenes).
Can I set this other navigation controller as the root controller also?
Like, can I have two root view controllers in a project?
It looks to me like there is a navigation bar visible (see screenshot below) on my new table view controller but I can't click in to it to edit it to add a title to it.
But does a navigation bar and exist, and if so, why can't I click inside it and use it?
I was told in an answer to a previous question that you have to add a navigation bar manually to your storyboard scene to any additional view controllers. I did that yday and it worked. But today when I tried to add a navigation bar by dragging onto scene it wouldn't let me do this.
Here is the screenshot:
Try adding push segue(which is depreciated) and than change it to a show segue(between your tableviews). This is a workaround I use in my apps.
Ran into the same problem. Had a good fallback position, I am doing a tutorial that came with example programs completed and working so the first thing I did was see if it was a version glitch between 6.3.2 and 6.4. Turned out the earlier project worked just fine.
So what I did was simply drag the 'Item' in the sidebar and moved it under the Root View Controller!
I've experienced the same issue.
However, by saving and closing the project then reopening it, the Navigation Bar title is then able to be edited. Prior to closing/reopening the project the field could not be edited.
I've spent the past few days searching on the web for a solution to my problem, however, I can't seem to find a problem similar to mine. I am using a TabBarController and on one of the tabs I have a segmented Control in the navigation bar that I would like to use to switch between view controllers. The problem is that when I present the second view Controller it appears over the tabbarcontroller. Is there anyway to keep the modally presented Navigation controller in the tabbarcontroller?
This is the first controller.
And this is the controller I am trying to present.
well we can't really comment unless we saw some code. But I think your problem may be to do with your view hierarchy. If I was going to build what you are attempting I would do as follows:
UITabbar controller that contains a custom navigation bar controller
The custom nav bar controller would contain the segment controller and have a protocol defined so that a delegate could be alerted when either segment was selected by the user.
The nav bar's root view controller would be a view controller that acted as a UIView container for the two screens you are displaying (friends and circle screens)
This root view controller would be the delegate for the custom nav controller so that it will know when the user selected a segment.
When the user selected a segment the root view controller would then switch between the friends and circles view controllers in the container.
To do the above have a look at the documentation for creating UIViewController Containers and working with delegates
Hope that helps!
I am creating a iPad App and it has several views to load data,but for one view i need to add split view. I dont need split views in other views. They are just detail pages. I search Through the net and found lots of tutorials based on iPad split view. But the problem is they all are creating a project as Split view project or they create a window base app and add slipt view to the delegate. I dont need to do that, I need to implement this split view only for one view. Is There any way to overcome this problem?
You can add the split view inside a Navigation Controller.
Even if the Split View is a container view controller and Apple recommends in the documentation that all containers should not be embedded in other containers, adding a split view inside a navigation controller works correctly and I never noticed any side effect in doing it.
Basically what you should do is:
- in the app delegate create a UINavigationController and use it as root view of your application window
- hide the navigation controller navigation bar if you don't want to see it (showing a split view with a main navbar on top is not nice looking...)
- then add your view controllers inside the navigation bar.
Example: imagine you have this application views sequence:
FIRST VIEW (full view = detail page)
SECOND VIEW (split view)
THIRD VIEW (full = detail page)
So you can represent FIRST and THIRD as standard view controllers (full screen), while SECOND will be a split view. Your app will be initialized by creating the main navigation controller, adding FIRST on it as top controller and using the main navigation controller as window's root view.
Than use the navigation controller push, pop methods to switch between these views or change the navigation controller "viewControllers" array directly if you don't want the recommended push/pop methods.
If you need to add special behavior to the navigation controller based on the type of view on top, just register your app delegate as navigation controller delegate (or a "main controller" object dedicated to this if you don't want to complicate your app delegate).
I am not 100% sure, but it seems to me that you can't use a SplitView just somewhere in your view hierarchy.
The Apple intended way is to use the SplitViewController as the top level controller. The left side of it can include a drill down mechanism with a navigation controller so you are ably to drill down hierarchies and the right side will present details for the item you select on the left side.
If you need a view with some kind of split mechanism in it, you probably have to code it yourself. Or even better: find some other mechanism you can use in your UI.
How are you switching your view hierarchies now? Maybe you could integrate your existing UI into a SplitViewController?