Tab bar items are the same except for their data set in storyboard - ios

I've set up a storyboard with a UITabBarController object and I'd like to add two tabs to that, but both tabs are going to be exactly the same except for the data they will display. Obviously, I could drag in two new view controllers and connect them up and just maintain the views separately, but I don't want to do this at all.
Does anyone know the most efficient way of doing this?

I've done this by using a regular UIViewController with a tab bar at the bottom, rather than using a UITabBarController. You just have to use the UITabBar delegate method, tabBar:didSelectItem:, to detect the tab clicks, and then do whatever you need to do to switch what data is displayed in the single view.

Related

Using a UITableView to populate a UITabBar

I am converting my single view application into one that is based on tabs. I have most of the layout done so I'm trying to wire up all the components now and I'm stuck trying to figure out how to do two things:
When I pick a bonus from my UITableView, I want it to open my 2nd tab with the info for the selected row. I'm not sure how to do that.
If I go straight to one of the other tabs, I want to have it just display the details for the first visible row of the UITableView. I'm not sure how to set such a default value.
I'm not exactly sure what code you would need to see for the above, but I am using Xcode 9 and Swift 4. I've googled and searched YouTube and Stack Overflow, and the answers are either all for Objective-C or are about the UITabBar obscuring the last row of UITableView data (which is not an issue I'm having).
EDIT: I seem to have semi-gotten it to work by changing my prepare (for segue) and then via Interface Builder, deleting the segue from the UITableView to the tab's viewController. However, this still doesn't light up the proper tab in the UITabBar. Also, this is still wrapped in the original Navigation Controller. Which allows me to move back and forth, but isn't the intent. When I tried removing the Navigation Controller, I had to use a "Show" or "Modal" type segue, which covers up the UITabBar, and offers no way to get back out of the detail view. I want to use the UITabBar to provide the back and forth that the Navigation Controller used to handle so I can gain the space at the top of the screen back.
The simplest is probably to register a Notification Center observer in your second tab's view controller. Whenever you have an item to show, simply trigger the notification from your first tab's view controller attaching the object you need to show to the notification.

Custom controls in UITabBarController

Is it possible create such element on base UITabBarController?
If not, how do you advise create it. Thank you,
Is it possible create such element on base UITabBarController?
No, you cannot add your own controls to a tab bar. The tabs in a tab bar should be used as they're intended, i.e. to switch between several different view controllers.
If not, how do you advise create it.
I recommend that you don't try to create something that both switches between view controllers and also does other things. That said, if you want to add controls that work differently from tabs in a bar at the top or bottom of the window, UIToolbar is the right class to use. You might be able to create a subclass of UIBarButtonItem that has radio-button functionality similar to what UISegmentedControl offers, and you could then use that with UIToolbar.
I do not think you can easily add a UISegmentControl to a UITabBarController. If you check Apple Documentation UITabBarController accepts UITabBarItems which can be initialize with either an image/String or with one of the preset cases.
You could create your own TabBar and then add a UISegment Control onto that, but if I was you I would use the normal UITabBarController and make the two buttons one next to the other with images that makes it look like a segment control to the user.
The issue with this approach that the TabBar is not supposed to be there for you to have more than one item selected at a time. So you could not have notes and All selected at once.
It might be easier for you to add the UISegmentControl onto a UINavigationController at the top of your app, and then use the TabBar normally.
That is what I would do in any case.

Keep state of navigation controller and only change view

I have an application with a drop down menu as the titleView of my NavigationController. When a user selects an item of the drop down menu, the entire view should switch contents, however, the NavigationBar should remain the same. The NavigationBar should not have to reload any data and the titleView should remain a drop down menu.
The original view upon opening the app:
The view upon touching the dropdown menu:
I currently see a few ways of going about this:
Set up a UIViewController for each option, perform the segue, and reload the data.
Why this is bad: I will have to set up a segue identifier for each ViewController, meaning if I have 15 options in my drop down menu, I will have 210 segue identifiers laying around. I will also have to reload all of my NavigationBar data.
Why this is good: I will have a clear area to set up each individual view.
Programmatically add and remove UIButtons, UILabels, and UIWhatevers as I need them.
Why this is bad: This will create a lot of code inside just one ViewController and things could get difficult to debug.
Why this is good: The NavigationBar never gets reloaded.
Add a container and embed a unique ViewController for each item as I need it.
Why this is bad: All of my work would still be in the main ViewController and I'd have to manage the logic of the embedded ViewController inside one Controller.
Why this is good: The NavigationBar never gets reloaded.
A completely different method suggested by someone else because I don't know the most efficient way of doing this.
So, in conclusion, what is the most efficient way to maintain state of my NavigationBar when switching my main content in my View?
Option 3 is the best out of the three you listed. Options 1 and 2 will get more and more complicated the more view controllers you want to add. Compare that to UINavigationController, UITabBarController, or UIPageViewController which do not need to be more complicated in order to handle 10 screens vs. 100 screens.
I would suggest creating a custom container view controller (Apple's Reference)
I see 2 immediate approaches to implementing this:
Subclassing UIViewController - this is how Apple's container view controllers are implemented
Subclass UITabBarController - I have done this successfully, subclassing UITabBarController to show a custom tab bar at the top instead of along the bottom.

TabBarController Smooth Slide

I have created a tab bar controller and I noticed that when I change tabs its an abrupt change-scene. Is there a way to make it so that when a tab is changed it slides to that tab?
I don't think, that this is possible with a UITabBarController. If you want an animated change between the content, you will need to implement another structure. You could for example use a collectionview, where the cells hold your content-controllers views, and where you change to the other view per button-tap-action and call collectionView.scrollToItemAtIndexPath()

Swap/ Transitioning between views iOS programming

I am a newbie to IOS programming and currently i have a tab bar application with two tabs. I have two questions.
The first tab shows a map, imagine it with some pushpins. There is a button on the navigation bar and when this is clicked i want the map view to to move out and a list view to come in. You can see the UI from the image. The button is called list.
Now when i click list I want this view to go away and the list view to come in. So here are my questions ?
1) How do i do this ? I tried the navigation model but i don't want that because I do not want a back button. I tried to make two different views and just dragged the button to that view but the app crashes. I just want the list button on the nab bar and when clicked the view changes to the list view and the button text changes to map. So now if I click the button again it should go back to the map view and the button changes to list.
2) How do i achieve the animations for this ? Ive seen some app where the page flips around and I've seen some options like reducing the opacity etc but I want to achieve the flip animation.
Thank You for any help I get. I really appreciate it.
Interface Builder can do most of this. Hold down the control key and drag from your map View Controller's UIBarButtonItem titled "List" to your list View Controller, then choose the Action Segue "modal". An arrow appears representing the segue; click on it and use the Attributes Inspector to change the Transition to "Flip Horizontal". Here's a video
Or, you could do this programmatically with presentViewController:animated:completion.
Now to get back to the map from the list, I believe that must be done programatically. Create a method that calls dismissViewControllerAnimated:completion: and make your list View Controller's UIBarButtonItem titled "Map" trigger it.
After reading your comments, I am wondering... if the structure of your app is logically a tabbed app structure (as indeed you refer to it as a 'tab bar application'), shouldn't you consider using the UITabViewController instead of a NavigationController? That is what it is designed to do, after all.
If you do use a TabViewController you should reconsider your desire for flip animation, as that doesn't really make UI-sense for tabs. If you can dispense with the flip animation, TabViewController could be a good way to go and you should at least experiment with that before dismissing the idea. It is also designed to grow... you can incorporate any number of tabs in a tab bar. Check out the apple docs (with pictures!)
You will notice that tabs are at the foot of the screen, whereas your 'tab' navController buttons are in a navbar at the top of the screen. This also helps as your app grows, as it is straightforward - from a UI design point of view and programmatically - to incorporate navControllers as navigation tools within individual tabs. For example, if your map/list flip routine does indeed make sense for this part of you app, you can keep this as a single tab (in it's own navigationController) and add other tabs for other parts of the app...
update
From your comment, you are saying that you are interested in the navController-inside-tabBarController setup. In this case here are some ways to get flip transitions AND no back button..
(1) modal presentation
The easiest way to get what you want is to set up one of your viewControllers (say the map view) to present the other one (the list view) modally.
If in the storyboard:
embed your mapViewController in a navController with a navbar button for navigation to the listView as in your picture
add your listViewController to the storyboard and embed it in it's own navContoller (not the mapViewController's navController). Drag a barButtonItem to this navController and wire it up to an IBAction in listViewController
CTRL-drag from mapViewController's 'list' button to the listViewController to create a segue. Select the segue and in the attributes inspector set the segue type to 'modal', with transition 'flips horizontal' and 'animated' checked. Give it a name in case you want to refer to it in code.
in the listViewController's IBAction add this:
[[self presentingViewController] dismissViewControllerAnimated:YES completion:nil];
That should achieve your result. You can use the completion block to send information back from the list view to the map view, and/or set the map view as the listView's delegate.
If you are not using the storyboard check this apple guide
Presenting View Controllers from Other View Controllers
especially "Presenting a View Controller and Choosing a Transition Style".
There is one catch with this approach - when the presented view flips onto the screen, the entire previous view, including the tab bar, is flipped out of the way. The idea is that this is a modal view which the user is required to dismiss before doing anything else in the app.
(2) push/pop in a single navController If this does not suit your intent, you can navigate using a single NavigationController with push and popping of views, and you can hide the back button ... but you really would need to keep the back button functionality as you do want to go back to the mapView, not on to a new map view.
To hide the back button try:
self.navigationItem.hidesBackButton = YES
in the uppermost viewControllers' viewDidLoad
Then you can add a barButtonItem in the xib/storyboard, with this kind of IBAction:
[self popViewControllerAnimated:NO]
or
[self popToRootViewControllerAnimated:NO]
You would have to construct the flip animation in code as it is not supported as a built-in with UINavigationController (best left as an exercise for the reader!)
(3) swapping views in a single viewController As ghettopia has suggested, you could use a single viewController inside a navController (or with a manually place navBar) and swap two views around using the UIView class methods
transitionFromView:toView:duration:options:animations:completion
transitionWithView:duration:options:animations:completion.
This could be a good simplifying solution as your list and map are essentially two views of the same data model.

Resources