Rxswift: Why is the NSControl.rx.value static func non-public?

Created on 9 Nov 2016  路  3Comments  路  Source: ReactiveX/RxSwift

Short description of the issue:

When creating a custom ControlProperty

Expected outcome:

Can use NSControl.rx.value(base, getter, setter)

What actually happens:

Can not use NSControl.rx.value(base, getter, setter)

Platform/Environment

  • [ ] iOS
  • [x] macOS
  • [ ] tvOS
  • [ ] watchOS
  • [ ] playgrounds

How easy is to reproduce? (chances of successful reproduce after running the self contained code)

  • [x] easy, 100% repro
  • [ ] sometimes, 10%-100%
  • [ ] hard, 2% - 10%
  • [ ] extremely hard, %0 - 2%

Level of RxSwift knowledge:
(this is so we can understand your level of knowledge
and formulate the response in an appropriate manner)

  • [ ] just starting
  • [ ] I have a small code base
  • [x] I have a significant code base

See RxCocoa/macOS/NSControl+Rx.swift

Why can't value be public?

Most helpful comment

Finally I've found the solution as explained here 681

In case your project is in Swift3, here is the snippet for valuePublic

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

For completeness, here is how you expose a custom control property

extension Reactive where Base: CustomControl {

    /**
     Reactive wrapper for `on` property.
     */
    internal var value: ControlProperty<T> {
        return UIControl.valuePublic(
            self.base,
            getter: { customControl in
                customControl.customProperty
        }, setter: { customControl, value in
            customControl.customProperty = value
        }
        )
    }
}

All 3 comments

I'm currently facing the exact same issue. Please let us know if there is a way around this. Thanks!

Finally I've found the solution as explained here 681

In case your project is in Swift3, here is the snippet for valuePublic

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

For completeness, here is how you expose a custom control property

extension Reactive where Base: CustomControl {

    /**
     Reactive wrapper for `on` property.
     */
    internal var value: ControlProperty<T> {
        return UIControl.valuePublic(
            self.base,
            getter: { customControl in
                customControl.customProperty
        }, setter: { customControl, value in
            customControl.customProperty = value
        }
        )
    }
}

Merci Philippe !

Was this page helpful?
0 / 5 - 0 ratings