You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift 4.2中如何在运行时根据变量切换Tab Bar Item非选中图片?

解决方案:动态切换Tab Bar Item非选中图片

嘿,我来帮你搞定这个在Swift 4.2、Xcode 10.1环境下动态切换Tab Bar Item非选中图片的问题!你之前遇到的问题大概率是因为只在初始化阶段设置了一次,没有监听truth变量的变化,或者没有处理图片的渲染模式导致颜色不生效。下面给你两种可行的实现方式:

方案一:给truth变量添加属性观察者,实时更新

这种方式适合truth变量在当前视图控制器中管理的场景,当truth的值变化时,立刻触发Tab Bar Item的图片更新:

// 假设truth是当前控制器的属性
var truth: Bool = false {
    didSet {
        // 确保能获取到对应的Tab Bar Item
        guard let tabBarItems = tabBarController?.tabBar.items else { return }
        let targetTabItem = tabBarItems[0]
        
        // 根据truth状态选择非选中图片
        let unselectedImageName = truth ? "globe_red" : "globe"
        // 关键:设置图片的渲染模式为.alwaysOriginal,避免被TabBar的tintColor覆盖颜色
        targetTabItem.image = UIImage(named: unselectedImageName)?.withRenderingMode(.alwaysOriginal)
        
        // 重新确认选中图片,防止被意外修改
        targetTabItem.selectedImage = UIImage(named: "globe")?.withRenderingMode(.alwaysOriginal)
    }
}

注意点:

  • 必须设置withRenderingMode(.alwaysOriginal):默认情况下UIImage会使用.automatic渲染模式,TabBar的tintColor会覆盖图片原本的颜色,导致你的红色图片显示不出来。
  • 如果你的truth是在其他类中管理的,可以把这个更新逻辑封装成一个公共方法,在truth变化时调用。

方案二:子类化TabBarController,监听状态变化

如果truth是全局状态(比如存储在UserDefaults或者全局单例中),可以通过子类化TabBarController来统一管理Tab Bar的状态更新:

第一步:创建自定义TabBarController

class CustomTabBarController: UITabBarController {
    override func viewDidLoad() {
        super.viewDidLoad()
        // 初始化时先设置一次初始状态
        updateTabBarItemImage()
        
        // 添加通知观察者,监听truth的变化
        NotificationCenter.default.addObserver(
            self,
            selector: #selector(updateTabBarItemImage),
            name: NSNotification.Name("TruthStateDidChange"),
            object: nil
        )
    }
    
    @objc private func updateTabBarItemImage() {
        guard let tabBarItems = tabBar.items else { return }
        let targetItem = tabBarItems[0]
        
        // 替换成你的truth获取方式,比如从全局单例或UserDefaults读取
        let isTruthEnabled = YourGlobalState.shared.truth
        let unselectedImageName = isTruthEnabled ? "globe_red" : "globe"
        
        targetItem.image = UIImage(named: unselectedImageName)?.withRenderingMode(.alwaysOriginal)
        targetItem.selectedImage = UIImage(named: "globe")?.withRenderingMode(.alwaysOriginal)
    }
    
    deinit {
        // 记得移除观察者,避免内存泄漏
        NotificationCenter.default.removeObserver(self)
    }
}

第二步:在truth变化时发送通知

// 假设truth在全局单例中
class YourGlobalState {
    static let shared = YourGlobalState()
    var truth: Bool = false {
        didSet {
            // 发送通知告知TabBarController更新
            NotificationCenter.default.post(
                name: NSNotification.Name("TruthStateDidChange"),
                object: nil
            )
        }
    }
}

额外提示:避免初始化时tabBarController为nil的问题

如果你在子控制器的viewDidLoad中尝试获取tabBarController,可能会因为控制器还没被添加到TabBarController中而返回nil。这种情况下,可以把初始化代码放到viewWillAppear中:

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    // 初始化时设置一次图片状态
    updateTabBarItemImage()
}

private func updateTabBarItemImage() {
    guard let tabBarItems = tabBarController?.tabBar.items else { return }
    let targetItem = tabBarItems[0]
    let unselectedImageName = truth ? "globe_red" : "globe"
    targetItem.image = UIImage(named: unselectedImageName)?.withRenderingMode(.alwaysOriginal)
    targetItem.selectedImage = UIImage(named: "globe")?.withRenderingMode(.alwaysOriginal)
}

内容的提问来源于stack exchange,提问作者ljelliot

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 07:17:44