2

UIButton可以配置为在启用或禁用按钮时使用不同的样式、标题等,例如使用UIButton.setTitle(String, forState:UIControlState).

ReactiveCocoa让我连接ReactiveSwift.Action到按钮的reactive.pressed属性,如果Action禁用,按钮将显示禁用样式:太棒了!

但是,当 a正在进行ReactiveSwift.Action时,它也会被禁用。SignalProducer这种锁定对于附加到慢动作(例如网络请求)的 UI 元素很有用,但当动作快速但非即时时会产生不希望的视觉闪烁。

一个简单的解决方法是不使用内置的UIButton禁用样式:相反,我们可以在Property<Bool>某处公开一个并使用它来启用/禁用Action和显式更改按钮的样式。然而,这有点笨拙和尴尬,所以我的问题是:是否有一种“干净”的方法可以将UIButton内置的禁用样式与通过显式禁用Actioninside禁用按钮相结合UIButton.reactive.pressed而不在操作进行时显示禁用的样式?

4

1 回答 1

2

我们最终使用位集中的application保留区域UIControlState明确编码:

extension UIControlState {
    public static var myActionIsExecuting = UIControlState(rawValue: 1 << 16)
}

public class ReactiveAwareStylingButton: UIButton {
    override public var state: UIControlState {
        return [super.state, customState]
    }
    var customState: UIControlState {
        if reactive.pressed?.isExecuting.value == true {
            return [.myActionIsExecuting]
        }
        return []
    }
}

这样我们就可以使用标准的依赖于状态的样式选项,例如

button.setTitleColor(normalColor, for: .normal)
button.setTitleColor(normalColor, for: [.disabled, .myActionIsExecuting])
button.setTitleColor(disabledColor, for: .disabled)

如果需要,我们还可以选择在操作执行时使用禁用的样式(这可能适用于慢速操作,例如网络请求),只需忽略.myActionIsExecuting状态即可。

如果应用这种技术,请注意编译器会很高兴地允许您犯语义错误:您可以将上述样式应用于不是自定义子类的UIButton实例,该实例永远不会进入状态。您应该防止出现此错误,例如,仅在带参数的函数中应用样式。ReactiveAwareStylingButton.myActionIsExecutingReactiveAwareStylingButton

于 2018-06-27T07:37:51.853 回答