UIButton上的RxSwift和isSelected属性 [英] RxSwift and isSelected property on UIButton

查看:1393
本文介绍了UIButton上的RxSwift和isSelected属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have three buttons and I want them to be selected only one at a time:

和:

等...

我的方法是这样的:

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来做到这一点?

Is there a better approach? It works, but is there a better 'reactive' way to do it by using RxSwift?

推荐答案

Subject和扩展名Variable在大多数情况下仅在从命令式世界过渡到反应性世界时才有用.在这里,您可以不用它们.

Subject and by extension Variable are most of the time only useful when bridging from imperative to reactive world. Here, you could do without them.

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

.do(onNext:) is also a way to perform side effect, something you usually don't want in your reactive code.

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

这篇关于UIButton上的RxSwift和isSelected属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆