The OP was for iOS 26.0. Meanwhile iOS 26.1 fixed the issue. .isEnabled property disables the tab bar item (goes gray) and prohibits user interaction (can't be selected).
@matt's answer works fine.
func tabBarController(\_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool {
if #available(iOS 26.0, *) { // run only if iOS >= 26.0
if #available(iOS 26.1, *) { // run only if iOS >= 26.1 (bug was fixed)
return true
}
if (condition_when_tab_bar_item_should_be_disabled) {
return false
}
}
return true
}
Changing my code back to the .isEnabled state from before iOS 26, I noticed that it doesn't work correctly when using .isEnabled inside DispatchQueue.main.async. It is simply ignored like it was for iOS 26. Flagging the property or layout for an update doesn't do anything either. However re-setting the tab bar item image makes the .isEnabled property change to be considered.
@objc func disableTab() {
DispatchQueue.main.async { // required otherwise crashes
self.tabBar.items?\[0\].isEnabled = false
// if #available(iOS 26.0, *) {
// self.tabBar.updatePropertiesIfNeeded() // doesn't do anything
// }
// self.tabBar.setNeedsLayout() // doesn't do anything
// self.tabBar.layoutIfNeeded() // doesn't do anything
if #available(iOS 26.0, *) { // this works!
let image = self.tabBar.items?\[2\].image
self.tabBar.items?\[2\].image = nil
self.tabBar.items?\[2\].image = image
}
}
}
Hope this helps somebody having the same issue.