Как вызвать действие для rx.tap.bind UIButton?

avatar
Bartłomiej Semańczyk
1 июля 2021 в 16:59
465
1
1

У меня просто что-то вроде этого:

    class CheckboxView: UIView {
        private let button = UIButton()
        var rxaction: RxSwift.Reactive<UIButton> {
            button.rx
        }
    }

    let view = CheckboxView()

    view.rxaction.tap.bind { in
          print(sth)
    }.disposed(by: disposeBag)

Как выполнить действие вручную, используя rxaction, чтобы вызвать закрытие привязки?

Источник
Daniel T.
1 июля 2021 в 21:09
0

Что вы подразумеваете под "выполнить действие вручную"? Весь смысл Rx в том, что вы не делаете таких вещей. Действие должно быть результатом какого-то события, которое происходит.

Ответы (1)

avatar
Daniel T.
3 июля 2021 в 13:50
1

Суть функционального реактивного программирования заключается в том, чтобы полностью указать динамическое поведение значения во время его объявления. -- Генрих Апфельмус

Поэтому, желая выполнить действие вручную, вы неправильно используете FRP. Тем не менее, переход к мышлению FRP может быть трудным.

Если вы хотите иметь дело с Наблюдаемым в императивном поместье, вам нужен Субъект. В вашем случае цель состоит в том, чтобы создать событие либо при нажатии кнопки, либо в обязательном порядке. Итак, вы делаете это следующим образом:

class CheckboxView: UIView {
    private let button = UIButton()
    private let _manualAction = PublishSubject<Void>()

    let tap: Observable<Void>

    override init(frame: CGRect) {
        tap = Observable.merge(
            button.rx.tap.asObservable(),
            _manualAction
        )
        super.init(frame: frame)
    }

    required init?(coder: NSCoder) {
        tap = Observable.merge(
            button.rx.tap.asObservable(),
            _manualAction
        )
        super.init(coder: coder)
    }

    deinit {
        _manualAction.onCompleted()
    }

    func actManually() {
        _manualAction.onNext(())
    }
}

Обратите внимание, что tap — это let, а не var, потому что, если вы сделаете его var, он может быть заменен, что а не<503739638535> лишает подписчиков3. Они продолжали бы указывать на предыдущий объект и заставляли его оставаться в живых.

Также обратите внимание, что я не использую вычисляемое свойство. Это потому, что это будет создавать разные Observable каждый раз, когда вызывается tap. В общем, это не то, чего вы хотите, поэтому вы должны сделать привычкой избегать этого. (В данном конкретном случае результатом является горячий Observable, так что это можно было бы сделать, но если вы делаете это регулярно, вы будете ошибаться большую часть времени.)

Наконец, вам может быть интересно, почему вам нужно пройти через все это только для того, чтобы вручную активировать подписку. Опять же, помните, что ручные триггеры противоречат сути FRP. Вам следует избегать этого.