Есть ли способ декларативно отправлять обновления наблюдаемому объекту после его определения?

Я изучаю Rx и хотел посмотреть, смогу ли я декларативно определить ввод и некоторого элемента пользовательского интерфейса в терминах друг друга до того, как компонент этого элемента будет инициализирован.

Вот как это будет выглядеть:

class ViewController: UIViewController {
    @IBOutlet weak var button: UIButton!

    var child: ButtonComponent!

    override func viewDidLoad() {
        super.viewDidLoad()

        let buttonInput = PublishSubject<()>()
        let buttonOutput = buttonInput
            .scan(0) { count, _ in
                count + 1
            }
            .map { $0.description }

        self.child = ButtonComponent(
            button: self.button,
            input: buttonInput,
            output: buttonOutput
        )
    }
}

class ButtonComponent {
    weak var button: UIButton!
    let disposeBag = DisposeBag()

    init(button: UIButton, input: PublishSubject<()>, output: Observable<String>) {
        self.button = button

        output
            .subscribeNext { string in
                button.setTitle(string, forState: .Normal)
            }
            .addDisposableTo(disposeBag)

        button.rx_tap
            .subscribeNext {
                input.onNext($0)
            }
            .addDisposableTo(disposeBag)
    }
}

Проблема здесь в том, что я использую PublishSubject для отправки обновлений во входной поток, что является обязательным и не рекомендуется. Предоставляет ли Rx способ каким-то образом добавить последовательности к уже работающему наблюдаемому объекту?


person mschumacher    schedule 05.01.2016    source источник
comment
Ответ на ваш последний вопрос - да, используя Observable.Merge. Хотя я не совсем уверен, как это применить здесь...   -  person supertopi    schedule 10.01.2016


Ответы (1)


После некоторых исследований кажется, что нет. Просто потому, что если вы хотите добавить последовательность к уже работающему наблюдаемому объекту, это мутация. И нет декларативного способа сделать мутацию.

Я посмотрел на библиотеку javascript под названием cycle.js, которая делает то же самое, и они решили ее аналогичным образом с помощью ReplaySubject.

Единственное, что вы можете сделать, это сделать его немного красивее, выполнив

button.rx_tap
    .subscribe(input)

Вместо

button.rx_tap
    .subscribeNext {
        input.onNext($0)
    }
person mschumacher    schedule 10.01.2016
comment
Это неправда. Оператор merge позволит вам добавить к уже работающему наблюдаемому объекту. - person Enigmativity; 10.01.2016
comment
merge возвращает новую наблюдаемую, она не может изменить наблюдаемую. - person mschumacher; 10.01.2016
comment
Да, но если вы вставите слияние в запрос во время компиляции, вы сможете вставлять значения во время выполнения. - person Enigmativity; 10.01.2016
comment
Однако две последовательности, которые должны быть объединены, уже должны быть на месте. Проблема здесь в том, что я хочу определить buttonOutput с точки зрения buttonInput еще до того, как у меня будет ввод кнопки. - person mschumacher; 10.01.2016