UITabBarController视图切换动画及自定义类方法点击不触发问题
解决UITabBarController自定义子类方法不触发+实现切换动画的方案
我来帮你一步步排查问题并实现想要的动画效果,大概率是几个常见的细节没做好:
一、先搞定自定义TabBarController方法不触发的问题
1. 确认自定义类已正确关联到TabBarController实例
这是最容易踩的坑:
- 如果你用Storyboard/XIB:选中你的UITabBarController,打开右侧Identity Inspector(第三个标签页),在Class下拉框里选择你的自定义子类(比如
CustomTabBarController),别让它停留在默认的UITabBarController上。 - 如果是纯代码创建:确保初始化的是你的自定义子类,而不是系统默认的类,比如:
let tabBarVC = CustomTabBarController() window?.rootViewController = tabBarVC
2. 确保代理方法已正确设置&重写
UITabBarController的切换监听方法属于UITabBarControllerDelegate协议,哪怕是子类,也需要把delegate指向自己才能触发这些方法:
在自定义子类的viewDidLoad()里加上关键一行:
override func viewDidLoad() { super.viewDidLoad() self.delegate = self // 不设置这行,代理方法永远不会触发! }
然后正确重写代理方法,比如:
extension CustomTabBarController: UITabBarControllerDelegate { // 选中Tab前触发,返回true允许切换,false阻止切换 func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool { print("准备切换到\(viewController.title ?? "未知页面")") return true } // 选中Tab后触发 func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) { print("已切换到\(viewController.title ?? "未知页面")") } }
如果你不想用代理,也可以直接重写selectedViewController的didSet,更直接:
class CustomTabBarController: UITabBarController { override var selectedViewController: UIViewController? { didSet { guard let newVC = selectedViewController else { return } print("切换到了\(newVC.title ?? "未知页面")") // 这里可以直接触发动画逻辑 } } }
二、实现TabBar切换的自定义动画过渡
要实现视图间的动画,需要用UIViewControllerAnimatedTransitioning协议创建自定义动画器,再通过TabBarController的代理方法返回这个动画器:
1. 创建自定义动画器类
这里以左右滑入滑出为例,你可以根据需求修改动画逻辑:
class TabBarTransitionAnimator: NSObject, UIViewControllerAnimatedTransitioning { // 动画时长 func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval { return 0.3 } // 具体动画实现 func animateTransition(using transitionContext: UIViewControllerContextTransitioning) { guard let fromVC = transitionContext.viewController(forKey: .from), let toVC = transitionContext.viewController(forKey: .to), let containerView = transitionContext.containerView else { return } // 设置目标页面的初始状态(从右侧滑入) toVC.view.frame = containerView.frame.offsetBy(dx: containerView.bounds.width, dy: 0) containerView.addSubview(toVC.view) // 执行动画 UIView.animate(withDuration: transitionDuration(using: transitionContext), animations: { fromVC.view.frame = containerView.frame.offsetBy(dx: -containerView.bounds.width, dy: 0) toVC.view.frame = containerView.frame }) { finished in // 动画完成后恢复原页面位置,标记过渡结束 fromVC.view.frame = containerView.frame transitionContext.completeTransition(finished && !transitionContext.transitionWasCancelled) } } }
2. 在自定义TabBarController中返回动画器
在之前的代理扩展里添加这个方法:
extension CustomTabBarController: UITabBarControllerDelegate { // 返回自定义动画器,实现过渡动画 func tabBarController(_ tabBarController: UITabBarController, animationControllerForTransitionFrom fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? { return TabBarTransitionAnimator() } }
做完这些,点击TabBar Item时,不仅代理方法会正常触发,还会执行你自定义的切换动画。最后再检查一遍:类关联是否正确、delegate是否设置、方法签名有没有写错(Swift里协议方法的参数名很容易写错导致不触发)。
内容的提问来源于stack exchange,提问作者Tier
相关产品推荐
相关产品推荐

