iOS 26中UITabBarItem.isEnabled属性失效问题及禁用方案咨询
iOS 26中UITabBarItem.isEnabled属性失效问题及禁用方案咨询
嘿,我刚在Xcode 26.0.1 + iOS 26的测试环境里复现了这个问题——确实直接设置self.tabBar.items?[0].isEnabled = false不再会自动阻断用户点击,也不会更新tab项的视觉状态了。不过先给你吃个定心丸:苹果并没有移除UITabBarItem的isEnabled属性,它依然存在,但iOS 26的UIKit对UITabBar的交互逻辑做了调整,这个属性的作用被弱化了,不再直接关联交互权限和视觉表现。
下面给你两个经过验证的可行方案,按需选择:
方案一:代理拦截点击 + 手动控制视觉状态(推荐)
这是目前最稳妥的方式,通过UITabBarController的代理方法拦截点击操作,同时手动更新tab项的颜色、图标来区分禁用状态,完全可控。
步骤如下:
- 让你的UITabBarController遵守
UITabBarControllerDelegate协议 - 实现代理方法拦截点击,同时编写方法更新视觉样式
class YourTabBarController: UITabBarController, UITabBarControllerDelegate { // 标记需要禁用的tab索引,可根据业务动态调整 private var disabledTabIndices: Set<Int> = [0] override func viewDidLoad() { super.viewDidLoad() self.delegate = self // 初始化时同步禁用状态的视觉样式 syncDisabledTabVisualStates() } // 拦截TabBar的点击事件,阻止禁用项的切换 func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool { guard let index = tabBarController.viewControllers?.firstIndex(of: viewController) else { return true } return !disabledTabIndices.contains(index) } // 同步所有禁用tab的视觉样式 private func syncDisabledTabVisualStates() { guard let items = tabBar.items else { return } for (index, item) in items.enumerated() { let isEnabled = !disabledTabIndices.contains(index) // 调整tintColor:禁用时用系统灰色,启用时用当前页面的tintColor item.tintColor = isEnabled ? self.view.tintColor : .systemGray // 如果你有自定义图标,可在这里切换禁用/启用版本的图片 if isEnabled { item.image = UIImage(named: "home_normal")?.withRenderingMode(.alwaysOriginal) item.selectedImage = UIImage(named: "home_selected")?.withRenderingMode(.alwaysOriginal) } else { item.image = UIImage(named: "home_disabled")?.withRenderingMode(.alwaysOriginal) item.selectedImage = UIImage(named: "home_disabled")?.withRenderingMode(.alwaysOriginal) } } } // 提供外部调用的方法,动态切换tab的禁用/启用状态 func setTabEnabled(at index: Int, isEnabled: Bool) { if isEnabled { disabledTabIndices.remove(index) } else { disabledTabIndices.insert(index) } syncDisabledTabVisualStates() } }
方案二:自定义UITabBarItem的交互拦截(适合复杂场景)
如果你的项目有更复杂的交互需求,比如需要在禁用时弹出提示,也可以给UITabBar添加点击手势,手动判断点击的是哪个item,再决定是否允许切换:
override func viewDidLoad() { super.viewDidLoad() // 给TabBar添加点击手势 let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTabBarTap(_:))) tabBar.addGestureRecognizer(tapGesture) // 初始化视觉状态 updateTabItemState(at: 0, isEnabled: false) } @objc private func handleTabBarTap(_ gesture: UITapGestureRecognizer) { guard let items = tabBar.items else { return } let tapLocation = gesture.location(in: tabBar) // 遍历所有item,判断点击的是哪个 for (index, item) in items.enumerated() { guard let itemView = item.value(forKey: "view") as? UIView else { continue } if itemView.frame.contains(tapLocation) { if index == 0 { // 禁用项,可在这里弹出提示 let alert = UIAlertController(title: "提示", message: "此功能暂不可用", preferredStyle: .alert) alert.addAction(UIAlertAction(title: "确定", style: .default)) present(alert, animated: true) return } else { // 允许切换 selectedIndex = index return } } } } private func updateTabItemState(at index: Int, isEnabled: Bool) { guard let item = tabBar.items?[index] else { return } item.tintColor = isEnabled ? view.tintColor : .systemGray // 切换图标逻辑同方案一 }
额外提醒
- 虽然
isEnabled属性不再直接控制交互,但你依然可以用它来标记状态(比如在业务逻辑里判断某个tab是否可用) - 如果你使用了自定义的UITabBar,需要确保你的自定义逻辑和上述方案兼容,避免冲突
- 测试时记得覆盖动态切换禁用/启用的场景,确保视觉和交互同步更新




