Detect when a tab bar item is pressed
Doing it this way caused me an error
Changing the delegate of a tab bar managed by a tab bar controller is not allowed
This is what I did and it worked
- In you
ViewController
you inheritUITabBarControllerDelegate
- Set delegate in a
viewDidLoad
- Add a function
Example:
class MyClass: UIViewController, UITabBarControllerDelegate {
func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {
let tabBarIndex = tabBarController.selectedIndex
if tabBarIndex == 0 {
//do your stuff
}
}
override func viewDidLoad() {
super.viewDidLoad()
self.tabBarController?.delegate = self
}
}
Swift 5
To detect if a specific TarBarItem
has been selected I use this on my custom TabBarController
:
class MainTabBarController: UITabBarController, UITabBarControllerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
self.delegate = self
}
func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {
let selectedIndex = tabBarController.viewControllers?.firstIndex(of: viewController)!
if selectedIndex == 0 {
print("first tab bar was selected")
} else {
//do whatever
}
}
}
You don't want your view controller's base class to be a UITabBarDelegate. If you were to do that, all of your view controller subclasses would be tab bar delegates. What I think you want to do is to extend UITabBarController, something like this:
class MyTabBarController: UITabBarController, UITabBarControllerDelegate {
then, in that class, override viewDidLoad and in there set the delegate property to self:
self.delegate = self
Note: This is setting the tab bar controller delegate. The tab bar has it's own delegate (UITabBarDelegate), which the tab bar controller manages, and you are not allow to change.
So, now this class is both a UITabBarDelegate (because UITabBarController implements that protocol), and UITabBarControllerDelegate, and you can override/implement those delegate's methods as desired, such as:
// UITabBarDelegate
override func tabBar(tabBar: UITabBar, didSelectItem item: UITabBarItem) {
print("Selected item")
}
// UITabBarControllerDelegate
func tabBarController(tabBarController: UITabBarController, didSelectViewController viewController: UIViewController) {
print("Selected view controller")
}
I'm guessing you're probably more interested in the latter. Check out the documentation to see what each of these delegates provide.
Last thing, in your storyboard (assuming you are using storyboards), set your tab bar controller's class to MyTabBarController in the Identity Inspector, and you're good to go.
Swift 3/4
// UITabBarDelegate
override func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) {
print("Selected item")
}
// UITabBarControllerDelegate
func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {
print("Selected view controller")
}
Here is a version of @mbeaty's answer with a little more context. It is adapted from my fuller answer here.
import UIKit
class MyTabBarController: UITabBarController, UITabBarControllerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
// tell our UITabBarController subclass to handle its own delegate methods
self.delegate = self
}
// called whenever a tab button is tapped
func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {
if let firstVC = viewController as? FirstViewController {
firstVC.doSomeAction()
}
if viewController is FirstViewController {
print("First tab")
} else if viewController is SecondViewController {
print("Second tab")
}
}
// alternate method if you need the tab bar item
override func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) {
// ...
}
}
Set this as the Custom class of your Tab View Controller in IB.
Alternate solution
- Just do something in the
viewDidLoad
method of the tab's view controller. See this answer.