UIButton上的RxSwift和isSelected属性

时间:2017-02-18 18:01:26

标签: ios swift rx-swift rx-cocoa

我有三个按钮,我希望它们一次只能选择一个:

enter image description here

enter image description here

等...

我的方法是:

class MyController: UIViewController {

    @IBOutlet var buttonOne: UIButton!
    @IBOutlet var buttonTwo: UIButton!
    @IBOutlet var buttonThree: UIButton!

    var buttonOneIsSelected = Variable(true)
    var buttonTwoIsSelected = Variable(false)
    var buttonThreeIsSelected = Variable(false)


    override func viewDidLoad() {
        super.viewDidLoad()

        buttonOne.isSelected = true

        buttonOneIsSelected.asDriver()
            .drive(buttonOne.rx.isSelected)
            .disposed(by: disposeBag)
        buttonTwoIsSelected.asDriver()
            .drive(buttonTwo.rx.isSelected)
            .disposed(by: disposeBag)
        buttonThreeIsSelected.asDriver()
            .drive(buttonThree.rx.isSelected)
            .disposed(by: disposeBag)

        buttonOne.rx.tap.asObservable().map { (_) -> Bool in
            return !self.buttonOne.isSelected
        }
        .do(onNext: { (isSelected) in
            self.buttonTwoIsSelected.value = !isSelected
            self.buttonThreeIsSelected.value = !isSelected
        })
        .bindTo(buttonOne.rx.isSelected)
        .disposed(by: disposeBag)

        buttonTwo.rx.tap.asObservable().map { (_) -> Bool in
            return !self.buttonTwo.isSelected
            }
            .do(onNext: { (isSelected) in
                self.buttonOneIsSelected.value = !isSelected
                self.buttonThreeIsSelected.value = !isSelected
            })
            .bindTo(buttonTwo.rx.isSelected)
            .disposed(by: disposeBag)

        buttonThree.rx.tap.asObservable().map { (_) -> Bool in
            return !self.buttonThree.isSelected
            }
            .do(onNext: { (isSelected) in
                self.buttonOneIsSelected.value = !isSelected
                self.buttonTwoIsSelected.value = !isSelected
            })
            .bindTo(buttonThree.rx.isSelected)
            .disposed(by: disposeBag)
}

有更好的方法吗?它有效,但使用RxSwift是否有更好的“反应”方式?

1 个答案:

答案 0 :(得分:12)

Subject和扩展Variable大部分时间只有在从命令性到被动性世界的过程中才有用。在这里,你可以没有它们。

.do(onNext:)也是一种执行副作用的方法,这是您在反应式代码中通常不想要的。

// force unwrap to avoid having to deal with optionals later on
let buttons = [button1, button2, button3].map { $0! }

// create an observable that will emit the last tapped button (which is
// the one we want selected)
let selectedButton = Observable.from(
  buttons.map { button in button.rx.tap.map { button } }
).merge()

// for each button, create a subscription that will set its `isSelected`
// state on or off if it is the one emmited by selectedButton
buttons.reduce(Disposables.create()) { disposable, button in
    let subscription = selectedButton.map { $0 == button }
      .bindTo(button.rx.isSelected)

    // combine two disposable together so that we can simply call
    // .dispose() and the result of reduce if we want to stop all
    // subscriptions
    return Disposables.create(disposable, subscription)
}
.addDisposableTo(disposeBag)