【问题标题】:RxSwift and isSelected property on UIButtonUIButton 上的 RxSwift 和 isSelected 属性
【发布时间】:2017-07-08 05:00:58
【问题描述】:

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

和:

等等……

我的做法是这样的:

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?

【问题讨论】:

    标签: ios swift rx-swift rx-cocoa


    【解决方案1】:

    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)
    

    【讨论】:

    • 感谢您的回答。我对反应式编程很陌生。 reduce 运算符对我来说有点难以掌握。您是否有任何关于 RxSwift 的一般解释资源(或专门用于 reduce 运算符)以扩展我的知识?
    • reduce 实际上是一个常规的 swift 序列方法。它需要一个种子值和一个累加器。最简单的例子是[1, 2, 3].reduce(0) { $0 + $1 }。这将计算((0 + 1) + 2) + 3 = 6。在我们的例子中,结果可以被认为是Disposable.create(Disposable.create(Disposable.create(emptyDisposable, button1Disposable), button2Disposable), button3Disposable)
    • 伟大的@tomahh。如果我理解正确,reduce 方法让您有机会将函数应用于数组的每个元素,然后创建一个订阅,而不是在每个元素上创建一个订阅,对吗?您返回 Disposable 的原因是因为 bindTo 方法创建了 Disposable? reduce 里面的实现让我有点困惑。 (抱歉这些问题,但我想了解实施背后的基本原理:))
    • 你可以将reduce看作一个循环。我已经提出了一个gist,其中代码是在for循环中编写的,也许你会更容易掌握:)
    • 我是 rxSwift 的新手。你能解释一下为什么你将buttons.reduce与“Disposables.create”一起使用吗?我还想添加功能,例如是否已选择按钮然后取消选择它。我怎样才能实现这一点?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-01-10
    • 1970-01-01
    • 2011-12-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-07-09
    相关资源
    最近更新 更多