UIButton setImage 没有(立即)效果

问题描述 投票:0回答:1

考虑以下内置断言:

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

为什么?我是否做出了无效的假设?

ios swift uikit uibutton
1个回答
0
投票

来自苹果的文档

讨论

将图像关联到按钮时,至少应设置正常状态的图像。如果您没有为其他状态指定图像,则该按钮将使用与正常关联的图像。如果您没有指定正常状态的图像,则该按钮将使用系统值。

可能不太清楚的是,调用:

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)
    }
    
}

看起来像这样:

运行时,切换

.isSelected
开关,正如您可能猜到的那样,将
button.isSelected
设置为
true
false

切换按钮图像状态开关会将图像设置为图像(如果打开)或将其设置为

nil
(如果关闭)。

也许值得注意...

当按钮有:

btn.isSelected = true

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

可以在上面的示例代码中看到这一点,方法是将

.isSelected
切换为“开”,然后点击该按钮。我们不再看到“突出显示”的标题或图像。

如果这是您的预期行为,那就太好了!如果没有,您可能需要重新考虑您的方法。

© www.soinside.com 2019 - 2024. All rights reserved.