2017-05-04 16 views
1

私はUIControlのカスタムサブクラスを作成しています(私は描画メソッドをオーバーライドする必要があります)。isSelectedプロパティをモデルにバインドするためにRxSwiftを追加します。カスタムUIControlサブクラスとRxSwift

これまでのところとても良いです。これは正常に動作します。

私の問題は、ユーザーtouchUpInsideイベントに応じてisSelectedプロパティを変更する方法です。

私の最初の試みは、UicontrolののaddTargetメソッドを使用していたが、isSelectedの値を変更すると、プログラムControlProperty(DOCに記載されているように)によって報告されていません。しかし、私はこれを解決する別の方法を考え出すことができます。

助けてください。サブクラスの

ソースコード:

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

    } 
} 

感謝。

+0

あなたも 'RxCocoa'を使用していますか? – ozgur

+0

RxCocoaも使用します – t4ncr3d3

答えて

2

あなたは、あなたがあなた自身のコントロールクラスを作っているとあなたがコントロールは、あなたが望むように動作させるために、1つ以上のbeginTracking(_:with:)の、continueTracking(_:with:)endTracking(_:with:)、またはcancelTracking(with:)をオーバーライドする必要があり、Uicontrolのからサブクラス化されている場合。次に正しいイベントでsendActions(for:)を呼び出します。 UIControlの中にはRxがありません。 UIButtonからキューを取ると、それが強調表示し、自身のハイライトを消しできますが、あなたのコントロールは、自分自身を選択するべきではありません

(ユーザの指は、例えば、その上にあるとき。)

あなたのUicontrol、コードを適切に作成したらoutsideコントロールはRxを使用してそれを観察することができます。

次作品:

class ViewController: UIViewController { 

    @IBOutlet weak var yesNoButton: SYYesNoButton! 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     yesNoButton.rx.controlEvent(.touchUpInside) 
      .scan(false, accumulator: { !$0.0 }) 
      .bind(to: yesNoButton.rx.isSelected) 
      .disposed(by: bag) 
    } 

    let bag = DisposeBag() 
} 

@IBDesignable 
class SYYesNoButton: UIControl { 

    override func layoutSubviews() { 
     super.layoutSubviews() 
     backgroundColor = isSelected ? .green : .red 
    } 

    override var isSelected: Bool { 
     didSet { 
      super.isSelected = isSelected 
      backgroundColor = isSelected ? .green : .red 
     } 
    } 
} 
関連する問題