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

Swift4(Xcode9.3.1)中UIButton作为IBAction触发源时图片颜色重置问题

解决UIButton触发IBAction时图片颜色重置的问题

我完全懂你碰到的这个糟心问题——点击其他按钮时,第一个按钮的图片颜色能正常修改,但点击它自己的时候,颜色就会跳回默认黑色。结合你用的Swift 4、Xcode 9.3.1环境,这个问题的核心是UIButton在交互过程中会切换状态(正常、高亮、选中),系统会自动根据这些状态调整tint颜色,而你的代码逻辑刚好和系统的状态更新流程冲突了。

先拆解下问题根源:

  • 你之前在IBAction里反复调用withRenderingMode(.alwaysTemplate)重新生成图片,这会干扰按钮内部的状态管理,尤其是按钮处于高亮(触摸中)状态时,系统会优先使用状态对应的渲染逻辑。
  • 直接修改按钮内部imageView的tintColor,不如直接操作UIButton本身的tintColor属性——UIButton会自动把这个值同步给内部的imageView,还能更好地处理状态切换。

下面给你两种可行的解决方案,结合你的代码做了针对性修改:

方案一:提前设置图片为Template模式,直接操作按钮的tintColor

这是最简洁也符合Apple设计规范的方式:

  1. 在viewDidLoad里一次性把目标按钮的图片设置为alwaysTemplate模式,避免每次点击重复生成图片干扰状态。
  2. 在IBAction里直接设置按钮的tintColor,如果需要点击按钮时高亮状态不改变颜色,可以同步设置highlightedTintColor。

修改后的代码如下:

import UIKit
class ViewController: UIViewController {
    @IBOutlet weak var oneButton: UIButton!
    @IBOutlet weak var twoButton: UIButton!
    @IBOutlet weak var threeButton: UIButton!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // 提前将oneButton的图片设置为Template模式,只需执行一次
        if let originalImage = oneButton.imageView?.image {
            oneButton.setImage(originalImage.withRenderingMode(.alwaysTemplate), for: .normal)
            // 可选:让高亮状态的图片和正常状态保持一致,避免触摸时变色
            oneButton.setImage(originalImage.withRenderingMode(.alwaysTemplate), for: .highlighted)
        }
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
    
    @IBAction func myAction(sender: UIButton) {
        var targetColor: UIColor = .black
        switch sender {
        case oneButton:
            print("oneButton")
            targetColor = .red
        case twoButton:
            print("twoButton")
            targetColor = .blue
        case threeButton:
            print("threeButton")
            targetColor = .purple
        default:
            break
        }
        // 直接设置按钮的tintColor,替代修改内部imageView的操作
        oneButton.tintColor = targetColor
        // 可选:同步高亮状态的tintColor,彻底避免触摸时颜色重置
        oneButton.highlightedTintColor = targetColor
    }
}

方案二:通过按钮状态回调保持颜色(适合复杂状态场景)

如果你的按钮需要处理选中、禁用等更多状态,可以通过重写按钮的setHighlighted(_:)方法,或者监听touchDown/touchUpInside组合事件来确保颜色不被重置,但方案一已经能覆盖大部分常规场景。

为什么你的原始代码会出问题?

  • 点击oneButton时,按钮会进入highlighted状态,系统会自动使用默认的高亮tint颜色(未设置的话就是默认黑色),而你的代码在IBAction里设置imageView颜色的时机,刚好被系统的状态更新逻辑覆盖了。
  • 反复调用withRenderingMode(.alwaysTemplate)会导致图片实例被频繁替换,干扰按钮的状态图片缓存机制。

另外你补充的代码里,experiment分支无效的原因是:withRenderingMode(.alwaysTemplate)方法会返回一个新的UIImage实例,而不是修改原有的oneImage,所以oneImageView.image = oneImage本质还是用的非Template模式的原图,自然tintColor设置不会生效。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:07:12