swift UIButton setImage没有(立即)效果

kognpnkq  于 5个月前  发布在  Swift
关注(0)|答案(1)|浏览(55)

考虑以下内置Assert:

button.isSelected = true
button.setImage(nil, for: .selected)
assert(button.image(for: .selected) === nil) 
//^^^^^^^^^^^^^^ this trips with === and ==

字符串
为什么?我的假设是错误的吗?

mzillmmw

mzillmmw1#

Apple的docs

讨论

在将图像关联到按钮时,至少应始终为正常状态设置一个图像。如果未为其他状态指定图像,则按钮将使用与正常状态关联的图像。如果未为正常状态指定图像,则按钮将使用系统值。
目前尚不清楚的是,呼吁:

button.setImage(nil, for: .selected)

字符串
也可以读作:“未指定.selected状态的映像"。
因此,按钮将使用来自.normal的图像。
如果您想在将按钮状态设置为.selected删除图像:

button.isSelected = true
    button.setImage(nil, for: .normal)
    button.setImage(nil, for: .selected)


下面是一些示例代码:

class SelectedButtonVC: UIViewController {
    
    let button = UIButton()
    
    var toggles: [UISwitch] = []
    var imgs: [String : UIImage] = [:]
    let titles: [String] = [
        "Normal", "Highlighted", "Selected",
    ]
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        view.backgroundColor = .systemBackground
        
        var promptLabel: UILabel!
        var vSep: UIView!
        var hs: UIStackView!
        
        let stack = UIStackView()
        stack.axis = .vertical
        stack.spacing = 8
        
        let colors: [UIColor] = [
            .systemBlue, .systemRed, .systemGreen,
        ]
        let states: [UIControl.State] = [
            .normal, .highlighted, .selected,
        ]
        
        let largeConfig = UIImage.SymbolConfiguration(pointSize: 40, weight: .bold, scale: .large)
        
        for (t, c) in zip(titles, colors) {
            guard let f = t.first?.description else { fatalError() }
            guard let img = UIImage(systemName: "\(f.lowercased()).square.fill", withConfiguration: largeConfig)?.withTintColor(c, renderingMode: .alwaysOriginal) else {
                fatalError("Could not load system image for \(t.lowercased())")
            }
            imgs[t] = img
        }
        for (t, s) in zip(titles, states) {
            button.setTitle(t, for: s)
            button.setImage(imgs[t], for: s)
        }
        for (c, s) in zip(colors, states) {
            button.setTitleColor(c, for: s)
        }
        button.backgroundColor = UIColor(white: 0.9, alpha: 1.0)
        button.layer.cornerRadius = 8
        button.layer.borderWidth = 1
        
        promptLabel = UILabel()
        promptLabel.text = "This is a button..."
        stack.addArrangedSubview(promptLabel)
        
        stack.addArrangedSubview(button)
        stack.setCustomSpacing(20.0, after: button)
        
        vSep = UIView()
        vSep.backgroundColor = .gray
        vSep.heightAnchor.constraint(equalToConstant: 2.0).isActive = true
        stack.addArrangedSubview(vSep)
        
        hs = UIStackView()
        hs.spacing = 8
        hs.alignment = .center
        promptLabel = UILabel()
        promptLabel.text = "Toggle button.isSelected:"
        hs.addArrangedSubview(promptLabel)
        let sw = UISwitch()
        sw.isOn = false
        toggles.append(sw)
        hs.addArrangedSubview(sw)
        stack.addArrangedSubview(hs)
        
        vSep = UIView()
        vSep.backgroundColor = .gray
        vSep.heightAnchor.constraint(equalToConstant: 2.0).isActive = true
        stack.addArrangedSubview(vSep)
        
        stack.setCustomSpacing(20.0, after: vSep)
        
        promptLabel = UILabel()
        promptLabel.text = "Toggle button images for states:"
        stack.addArrangedSubview(promptLabel)
        
        titles.forEach { t in
            hs = UIStackView()
            hs.spacing = 8
            hs.alignment = .center
            promptLabel = UILabel()
            promptLabel.text = t
            hs.addArrangedSubview(promptLabel)
            let v = UIImageView(image: imgs[t])
            v.contentMode = .scaleAspectFit
            v.heightAnchor.constraint(equalTo: v.widthAnchor).isActive = true
            hs.addArrangedSubview(v)
            let sw = UISwitch()
            sw.isOn = true
            toggles.append(sw)
            hs.addArrangedSubview(sw)
            stack.addArrangedSubview(hs)
        }
        
        stack.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(stack)
        
        let g = view.safeAreaLayoutGuide
        NSLayoutConstraint.activate([
            
            stack.topAnchor.constraint(equalTo: g.topAnchor, constant: 40.0),
            stack.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 40.0),
            stack.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -40.0),
            
            button.heightAnchor.constraint(equalToConstant: 60.0),
            
        ])
        
        toggles.forEach { sw in
            sw.addTarget(self, action: #selector(swTapped(_:)), for: .valueChanged)
        }
        
        button.addTarget(self, action: #selector(btnTapped(_:)), for: .touchUpInside)
    }
    
    @objc func swTapped(_ sender: UISwitch) {
        guard let idx = toggles.firstIndex(of: sender) else { return }
        switch idx {
        case 1:
            button.setImage(sender.isOn ? imgs[titles[0]] : nil, for: .normal)
            ()
        case 2:
            button.setImage(sender.isOn ? imgs[titles[1]] : nil, for: .highlighted)
            ()
        case 3:
            button.setImage(sender.isOn ? imgs[titles[2]] : nil, for: .selected)
            ()
        default:
            button.isSelected = sender.isOn
            ()
        }
    }
    
    @objc func btnTapped(_ sender: UIButton) {
        print("button.isSelected =", sender.isSelected)
    }
    
}


看起来像这样:
x1c 0d1x的数据
运行时,切换.isSelected开关将把button.isSelected设置为truefalse
切换按钮图像状态开关将图像设置为图像(如果打开)或将其设置为nil(如果关闭)。
或许值得注意的是...
当按钮具有:

btn.isSelected = true

  • 正常 * 属性(标题、标题颜色、图像等)用于 * 突出显示 * 状态。

在上面的示例代码中可以看到,将.isSelected切换为On,然后点击按钮。我们不再看到“Highlighted”标题或图像。
如果这是你想要的行为,很好!如果不是,你可能需要重新考虑你的方法。

相关问题