I have created a custom control thad works as UISlider
. Now I want to use it with RxSwift and for this I need rx_value
like property for my control.
I have found RxSwift code for UISlider
on GitHub:
extension UISlider {
/**
Reactive wrapper for `value` property.
*/
public var rx_value: ControlProperty<Float> {
return UIControl.rx_value(
self,
getter: { slider in
slider.value
}, setter: { slider, value in
slider.value = value
}
)
}
}
It does look simple enough so I decided just to repeat it in my control but apparently rx_value
property of UIControl
is private. What could be a workaround for this?
UPDATE:
That is how I'm going to use this property:
var latestRank: Observable<Int> {
return oneSlider
.rx_distance.asObservable()
.throttle(0.5, scheduler: MainScheduler.instance)
.distinctUntilChanged()
and in viewModel:
distanceRank
.observeOn(MainScheduler.instance).subscribeNext { rank in
print(rank)
self.discoverNodes(true)
}
In viewModel distanceRank
is defined as this:
let distanceRank: Observable<Int>
And this is extension for rx_distance
:
#if os(iOS) || os(tvOS)
import Foundation
#if !RX_NO_MODULE
import RxSwift
import RxCocoa
#endif
import UIKit
extension OneSlider {
public var rx_distance: ControlProperty<Int> {
return UIControl.valuePublic(
self,
getter: { slider in
slider.distanceRank
}, setter: { slider, value in
slider.distanceRank = value
}
)
}
}
extension UIControl {
static func valuePublic<T, ControlType: UIControl>(control: ControlType, getter: ControlType -> T, setter: (ControlType, T) -> ()) -> ControlProperty<T> {
let values: Observable<T> = Observable.deferred { [weak control] in
guard let existingSelf = control else {
return Observable.empty()
}
return existingSelf.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)
})
}
}
#endif