【发布时间】:2017-10-02 21:31:23
【问题描述】:
我正在创建 UIControl 的自定义子类(我需要重写它的 draw 方法)并且我想添加 RxSwift 以将其 isSelected 属性绑定到我的模型。
到目前为止一切顺利。这很好用。
我的问题是如何更改值 isSelected 属性以响应用户 touchUpInside 事件?
我的第一次尝试是使用 UIControl 的 addTarget 方法,但 ControlProperty 不报告以编程方式更改 isSelected 的值(如文档中所述)。但我可以想办法解决这个问题。
任何帮助表示赞赏。
子类的源码:
class SYYesNoButton: UIControl {
override init(frame: CGRect) {
super.init(frame: frame)
// subscribe to touchUpInside event
addTarget(
self,
action: #selector(userDidTouchUpInside),
for: UIControlEvents.touchUpInside)
}
func userDidTouchUpInside() {
// change the value of the property
// this does not work,
// the change is not reported to the ControlProperty
// HOW CAN I CHANGE THIS ??
self.isSelected = !isSelected
}
}
添加响应式支持的扩展:
extension SYYesNoButton {
var rx_isSelected: ControlProperty<Bool> {
return UIControl.valuePublic(
self,
getter: { (button) -> Bool in
return button.isSelected
},
setter: { (button, value) in
button.isSelected = value
})
}
}
extension UIControl {
static func valuePublic<T, ControlType: UIControl>(_ control: ControlType, getter: @escaping (ControlType) -> T, setter: @escaping (ControlType, T) -> ()) -> ControlProperty<T> {
let values: Observable<T> = Observable.deferred { [weak control] in
guard let existingSelf = control else {
return Observable.empty()
}
return (existingSelf as UIControl).rx.controlEvent([.allEditingEvents, .valueChanged])
.flatMap { _ in
return control.map { Observable.just(getter($0)) } ?? Observable.empty()
}
.startWith(getter(existingSelf))
}
return ControlProperty(values: values, valueSink: UIBindingObserver(UIElement: control) { control, value in
setter(control, value)
})
}
}
谢谢大家。
【问题讨论】:
-
你也在使用
RxCocoa吗? -
我也使用 RxCocoa
标签: swift subclass rx-swift uicontrol