检测何时按下标签栏项目

Detect when a tab bar item is pressed

我有一个根视图控制器,它没有设置为故事板上任何视图控制器的自定义 class。相反,我所有的视图控制器都是 subclassing 这个 class 像这样。

// RootViewController
class RootViewController: UIViewController, UITabBarDelegate { 

    // This is not getting executed on any of the view controllers
    func tabBar(tabBar: UITabBar, didSelectItem item: UITabBarItem) {
        print("ddd")
    }
}

// Subclassing it 
class TopStoriesViewController: RootViewController {

}

但是当在子视图控制器上按下 tabbaritem 时,我似乎正在努力做某事classing rootviewcontroller,即没有打印消息。

您不希望视图控制器的基础 class 成为 UITabBarDelegate。如果你这样做,你所有的视图控制器子 classes 都将是标签栏委托。我想你想做的是扩展 UITabBarController,像这样:

class MyTabBarController: UITabBarController, UITabBarControllerDelegate {

然后,在 class 中覆盖 viewDidLoad 并在那里将委托 属性 设置为 self:

self.delegate = self

注意:这是设置标签栏控制器委托。选项卡栏有它自己的委托 (UITabBarDelegate),由选项卡栏控制器管理,您不能更改。

所以,现在这个 class 既是 UITabBarDelegate(因为 UITabBarController 实现了该协议),也是 UITabBarControllerDelegate,您可以根据需要 override/implement 这些委托的方法,例如:

// UITabBarDelegate
override func tabBar(tabBar: UITabBar, didSelectItem item: UITabBarItem) {
    print("Selected item")
}

// UITabBarControllerDelegate
func tabBarController(tabBarController: UITabBarController, didSelectViewController viewController: UIViewController) {
    print("Selected view controller")
}

我猜您可能对后者更感兴趣。查看文档以了解每个代表提供的内容。

最后一件事,在您的情节提要中(假设您使用的是情节提要),在身份检查器中将选项卡栏控制器的 class 设置为 MyTabBarController,您就可以开始了。

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")
}

这样做导致我出错

Changing the delegate of a tab bar managed by a tab bar controller is not allowed

这就是我所做的并且它 有效

  1. 在你身上ViewController你继承了UITabBarControllerDelegate
  2. viewDidLoad
  3. 中设置委托
  4. 添加功能

示例:

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
   }

}

这是@mbeaty 回答的一个版本,其中包含更多上下文。它改编自我的 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) {
        // ...
    }
}

在 IB 中将其设置为选项卡视图控制器的自定义 class。

备选方案

  • 只需在选项卡的视图控制器的 viewDidLoad 方法中执行一些操作。参见 this answer

我使用了这段代码,因为我需要知道选择了同一个视图控制器。

import UIKit

protocol CustomTabBarControllerDelegate {
    func onTabSelected(isTheSame: Bool)
}

class CustomTabBarController: UITabBarController, UITabBarControllerDelegate {
    override func viewDidLoad() {
        super.viewDidLoad()
        self.delegate = self
    }
    
    func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool {
        (viewController as? CustomTabBarControllerDelegate)?.onTabSelected(isTheSame: selectedViewController == viewController)
        
        //Uncomment this code if you use UINavigationViewController in some of your tab view controllers
        //if let navigationViewController = viewController as? UINavigationViewController {
        //    (navigationViewController?.viewControllers.first as? CustomTabBarControllerDelegate)?.onTabSelected(isTheSame: selectedViewController == viewController)
        //}

        return true
    }
}

第一个选项卡视图控制器

import UIKit

class Tab1ViewController: UIViewController, CustomTabBarControllerDelegate {
    func onTabSelected(isTheSame: Bool) { 
        print("Tab1ViewController onTabSelected")
        //do something
    }
}

第二个选项卡视图控制器

import UIKit

class Tab2ViewController: UIViewController, CustomTabBarControllerDelegate {
    func onTabSelected(isTheSame: Bool) { 
        print("Tab2ViewController onTabSelected")
        //do something
    }
}

不要忘记将 CustomTabBarController 设置为自定义 class 到故事板中的 TabBarController 并通过所有选项卡视图控制器实现 CustomTabBarControllerDelegate 协议。

故事板的结构可以如下所示,或者它可以为每个或某些选项卡视图控制器拥有自己的导航视图控制器(然后您需要取消注释代码)。

Swift 5

为了检测是否选择了特定的 TarBarItem 我在我的自定义 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
        }
    }

}

Swift 5个简单的方法享受

//MARK:- it will work in 
class TabBar: UITabBarController, UITabBarControllerDelegate {

}

代码

override func viewDidLoad() {
    super.viewDidLoad()

    self.selectedIndex = 1
    self.title = "Measure"

    self.delegate = self        
}

//MARK:-  UITabBarDelegate
override func tabBar(tabBar: UITabBar, didSelectItem item: UITabBarItem) {
    print("Selected item")
}

//MARK:- UITabBarControllerDelegate
func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {
    let selectedIndex = tabBarController.viewControllers?.firstIndex(of: viewController)!
    if selectedIndex == 0 {
        self.title = "History"
    }
    else if selectedIndex == 1{
        self.title = "Measure"
    }
    else if selectedIndex == 2 {
        self.title = "Setting"
    } else {
        //do whatever
    }
}