I'm looking to disable the functionality of pressing my tab bar and returning to the root view in the navigation hierarchy whilst also keeping this functionality for a button in my navigation bar.
So the only way I want the user to go back to the root view is by pressing the button in the navigation bar and not by tapping the tab bar button.
I've had a look around and tried several solutions but none seem to work as they disable the functionality for both the nav bar button and the tab bar button but not just the tab bar button.
Thanks!
A possibility would be to create a subclass of UITabBarController and to implement the UITabBarControllerDelegate protocol.
Then you could implement
- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController
and return NO, when the particular viewController is selected again.
A way to do this is is to save the recently selected item and to compare it with the currently selected one.
Came across this issue at the weekend. I kept finding my custom TabBarController was nil during appDelegate didfinishlaunching() method.
The way I got around it was to make my custom TabBarController a UITabBarControllerDelegate and then implemented the following delegate method withint he custom TabBarController class:
// Stops View Controllers from being dismissed when a tab is selected on the UITabBarController
public func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool {
return viewController != tabBarController.selectedViewController
}
Related
I have an app with a HomeView and a bottom TabBar which load other views on tap. On this TabBar bar I also have a More button which on click opens a listView, each cell of this view also opens other views. (When I'm talking about views, I mean new tunnels/navigation controllers are displayed for example: MyPicturesViewController, SettingsViewController etc...).
There is my problem, I have to implement a feature that from my HomeView on a button click it navigates to a specific view that is not on the TabBar but in the More list and also update the TabBar to highlight the More button.
I tried at first to navigate manually with this code:
let viewController = UIStoryboard.instantiate(NewViewController.self)
self.viewController?.navigationController?.pushViewController(viewController, animated: true)
it works pretty well
and then update the tabbar manually
self.viewController?.tabBarController?.selectedIndex = 4
But updating the TabBar redirect automatically to the selected index which is the More list view and don't even take in count the manual navigation I did in the previous code.
So my question is, is it possible to update TabBar bar without loading its own navigationcontroller? If not how can I achieve what I want to do, I tried many things such as create a navigationcontroller and its viewcontrollers and replace the tabbar viewcontrollers stacks but I didn't succeed.
Thank you in advance for those who will take time to help me!
Instead doing it before
self.viewController?.tabBarController?.selectedIndex = 4
Push your controller in tabBar delegate method
func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool {
if viewController == desiredNavigationController {
show(desiredNavigationController, animated: true) // push
return false
}
return true
}
How can one push a new navigation controller from an existing navigation controller, as is done for Facebook's instant articles pictured below?
In this case, would you have to create a view controller schema with a master navigation controller with a translucent navigation bar that wraps both the Facebook tab bar / navigation controller and the instant article navigation controller?
Facebook instant article
Edit: Added Snapchat example
Are you thinking of the different UINavigationBar rather than the UINavigationController? I think you can already change the bar appearance for a different UIViewController... if its being a problem then you can make a class for the UINavigationController and add functionality in there to change appearance of the bar for what ever the UIViewController is being viewed.
The delegate methods of the UINavigationController give you methods like
func navigationController(_ navigationController: UINavigationController, willShow viewController: UIViewController, animated: Bool)
Inside that you can put a check like
if viewController.isKind(of: SomeViewController.self) {
//make this specific change for it
} else if viewController.isKind(of: SomeOtherViewController.self) {
//make this specific change for this other viewController
} else {
//make this for all other
}
I'd like to add an action sheet that appears when tab bar center item is clicked. like in this example:
this is how it shows when center item is clicked
i have added the tab bar from storyboard and its working fine.
the hard part of it is how to keep the previous view and overlay the action sheet.
thanks in advance.
use this delegate function to intercept tab selection
for swift 3
func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool {
if self.tabBarController.customizableViewControllers.index(of: viewController) == 2 {
//display action sheet
return false
}
return true
}
for objective c
- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController {
//same logic above
}
You could simply create an empty view controller, and present the action sheet in viewDidAppear. But you have to think of what to do (e.g. which view controller to display)
after the user chose an option
if the user cancels the action
I am making an application with TabBar. In the Tab Bar there are 2 tabs. One of those tabs is history which is linked with a table view which shows history. I want to refresh that view every time when i click that so that i can get updated tableview. How can i do that? Thanks in advance.
You probably just need to put the reload call in the viewWillAppear of the viewController with the table you want to reload, then, every time it is presented it will reload the data.
Anyway, if you want to catch the tap on of the tabs, you need to subclass UITabBarController and then implement this method -(void)tabBar:(UITabBar *)tabBar didSelectItem:(UITabBarItem *)item
Hi easiest solution for swift 4, to reload view by tapping again on tab bar icon.
#objc
func tabBarController(_ tabBarController: UITabBarController,
didSelect viewController: UIViewController) {
if tabBarController.selectedIndex == 0 {
viewController.viewDidLoad()
}
}
I have UITabViewController running with UINavigationController. In each tab i have a different TableViews that are roots of my application tree.
When i click an item of table, it goes to next level viewing another, detailed TableView, still having TabBar and NavigationBar on screen. It works perfectly, except for one thing. If i'm viewing details in one tab, then switch to another tab, and go back again, then i still see my detail. What i want to achieve, is to reset tab after leaving it.
I expect that i have to put something in viewDidUnload or simmilar, but couldn't find the right solution.
Hope you can help.
at
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController
do
[viewController.navigationController popToRootViewControllerAnimated:YES];
That will navigate the tab's view controller to the root view whenever the tab is selected.
That's completely OK to keep your main window view controller (tab bar controller) instance at application delegate.
What you need to add is to set the delegate or whatever other initialized class to be the tab bar controller's delegate like this:
myTabBarController = [UITabBarController alloc ...
myTabBarController.delegate = self; // the app delegate will be also the tab bar delegate
in the app delegate, then you add the following method to the app delegate:
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController{
[viewController.navigationController popToRootViewControllerAnimated:YES];
}
The tab bar controller will call this method whenever it's tab is selected.
You will also want to make the application delegate confirm UITabBarControllerDelegate this way:
#interface PSAppDelegate : UIResponder <UITabBarControllerDelegate>
that will let the compiler know that app delegate must or might have the methods declared in the protocol and will also give you so convenient auto-complition of this method.
One way to do this is to get the view controllers associated with the tabviewcontroller and then create new objects.
self.tabBarController?.viewControllers! will get an array of viewControllers for the tab bar. In my case they are a UINavigationControllers but they could be anything. I then get the viewController associated with that and reset that.
If you don't have navigation controllers you can just create new view controller objects and go with that.
below is the solution in my case (with the navcontroller)
let vc = self.tabBarController?.viewControllers![0] as! UINavigationController
let newVC = YourViewControllerClass()
vc.viewControllers[0] = newVC as UIViewController
This replaces the old (populated) vc with a new one!