ControlProperty

예시) whiteSlider.rx.value는 controlProperty로 옵저버, 옵저버블 모두 가능함.

→ Binder : Write Only (Observer)

→ ControlProperty : Read/Write 모두 가 능)(Observer, Observable)모두 가능함.

@IBOutlet weak var resetButton: UIBarButtonItem!
   
   @IBOutlet weak var whiteSlider: UISlider!
   
   override func viewDidLoad() {
      super.viewDidLoad()
      //Observable로 동작함.
      whiteSlider.rx.value
         .map { value in
             print(value)
             return UIColor(white: CGFloat(value), alpha: 1.0)
             
         }
         .bind(to: view.rx.backgroundColor)
         .disposed(by: bag)
      //Observer로 동작함
      resetButton.rx.tap
         .map { Float(0.5) }
         .bind(to: whiteSlider.rx.value)
         .disposed(by: bag)

UISlider의 ControlProperty Extension예제

var color: ControlProperty<UIColor?>{
        return base.rx.controlProperty(editingEvents: .valueChanged) { slider in
            return UIColor(white: CGFloat(slider.value), alpha: 1.0)
        } setter: { slider, color in
            var white = CGFloat(1)
            color?.getWhite(&white, alpha: nil)
            slider.value = Float(white)
        }

    }

base.rx.controlProperty 정의 부분

/// Creates a `ControlProperty` that is triggered by target/action pattern value updates.
    ///
    /// - parameter controlEvents: Events that trigger value update sequence elements.
    /// - parameter getter: Property value getter.
    /// - parameter setter: Property value setter.
    public func controlProperty<T>(
        editingEvents: UIControl.Event,
        getter: @escaping (Base) -> T,
        setter: @escaping (Base, T) -> Void
    ) -> ControlProperty<T> {
        let source: Observable<T> = Observable.create { [weak weakControl = base] observer in
                guard let control = weakControl else {
                    observer.on(.completed)
                    return Disposables.create()
                }

                observer.on(.next(getter(control)))

                let controlTarget = ControlTarget(control: control, controlEvents: editingEvents) { _ in
                    if let control = weakControl {
                        observer.on(.next(getter(control)))
                    }
                }
                
                return Disposables.create(with: controlTarget.dispose)
            }
            .takeUntil(deallocated)

        let bindingObserver = Binder(base, binding: setter)

        return ControlProperty<T>(values: source, valueSink: bindingObserver)
    }

파라메터로 전달받은 UIControl Event가 발생하면 Next이벤트로 getter 메소드가호출됨.

바인딩 되는경우 새로운 바인더 생성