1

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
alexxjk
  • 1,681
  • 5
  • 18
  • 30
  • It's `public`. What makes you think it's `private`? https://github.com/ReactiveX/RxSwift/blob/353b0b5/RxCocoa/iOS/UIControl+Rx.swift#L66 – solidcell Jun 01 '16 at 15:52
  • I'm getting an error "Type 'UIControl' has no member 'rx_value'". And then I found this post: https://github.com/ReactiveX/RxSwift/issues/681. The problem however that it seems solution there doesn't work in my case. When I'm subscribing on the 'value' I get a notification only for the first value changing. – alexxjk Jun 01 '16 at 15:57
  • Ah I see, yea it's not included on the `RxCocoa` target. Can you show your actual code which attempts to use that solution? – solidcell Jun 01 '16 at 16:08
  • @solidcell I have added some parts of my code. Is there something else that could be useful? – alexxjk Jun 01 '16 at 16:23
  • It's still not clear how `latestRank` and `distanceRank` relate to each other, if at all, nor how you'll use `latestRank` nor how `distanceRank` nor `rx_distance` are defined. – solidcell Jun 01 '16 at 16:28
  • @solidcell I added some other parts. I'm sorry I'm doing it by parts but I'm afraid to much code will make question impossible to read. – alexxjk Jun 01 '16 at 16:42
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/113556/discussion-between-alexxjk-and-solidcell). – alexxjk Jun 01 '16 at 16:44
  • I'm having a similar problem trying to make a custom UI slider reactive. Did you find a solution? – jbm Sep 11 '17 at 23:41

0 Answers0