1

I am using Swift 4 and XCode 9. I am trying to programmatically control navigation in my UITabBarController. According to Apple's documentation, I need to implement the UITabBarControllerDelegate protocol. However, the method I implemented never get called:

import UIKit

class TabBarController: UITabBarController, UITabBarControllerDelegate {
    override func viewDidLoad() {
        super.viewDidLoad()

        tabBarController?.delegate = self
    }

    func tabBarController(_ tabBarController: UITabBarController,
            shouldSelect viewController: UIViewController) -> Bool {
        print("Should go here...")
        return true
    }
}

Any idea what I am doing wrong?

rmaddy
  • 314,917
  • 42
  • 532
  • 579
Phil
  • 879
  • 2
  • 10
  • 23
  • I suspect there's some typographic error that makes your method not match up with the delegate method it's meant to override, but I can't find the difference – Alexander Jan 19 '18 at 00:44
  • @Alexander All the methods in the delegate are optional, so no `override` keyword required. The issue was answered correctly, I was not properly initializing the controller. – Phil Jan 19 '18 at 02:11

3 Answers3

6

Your problem is that you are setting the wrong delegate. Update viewDidLoad to:

override func viewDidLoad() {
    super.viewDidLoad()

    self.delegate = self // or just "delegate = self"
}

The idea is that you want this tab controller to be its own delegate.

rmaddy
  • 314,917
  • 42
  • 532
  • 579
  • Why bother with that at all. As far as I know he can just remove UITabBarControllerDelegate from the declaration – Leo Dabus Jan 19 '18 at 00:44
  • 2
    @LeoDabus Not if he wants the tab controller to dictate whether a given tab can be selected or not. – rmaddy Jan 19 '18 at 00:45
  • 1
    `UITabBarController` doesn't implement `UITabBarControllerDelegate`. – mugx Jan 19 '18 at 00:47
  • @AndreaMugnaini just saw that it conforms to `UITabBarDelegate` not `UITabBarControllerDelegate` – Leo Dabus Jan 19 '18 at 00:49
  • @rmaddy Out of sheer curiosity, what exactly am I accessing when doing `tabBarController?`... what is injected there? – Phil Jan 19 '18 at 02:13
  • 1
    `UIViewController` provides the `tabBarController` property as a convenience so any view controller embedded in a tab bar controller can its parent tab bar controller. Since `UITabBarController` extends `UIViewController` is also has this property. In fact, if you embed a tab controller inside another tab controller, the child tab controller can use its `tabBarController` property to get the parent tab controller. In your case You are subclassing `UITabBarController` and you want to access `self`, not any parent tab controller. – rmaddy Jan 19 '18 at 03:39
0

To detect the item selected event, you have to override didSelect method.

override func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) {
    print("Should go here...")
}
Hades0103
  • 3
  • 6
  • 1
    This is called AFTER the new UIView is displayed. The OP wants to make the shouldSelect method get called so he can do something BEFORE the new UIView is displayed. – David Rector Nov 19 '18 at 22:21
0

The right method to implement is DidSelect.....