2016-01-05 4 views
6

Я изучаю 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 способ как-то добавить последовательности к уже запущенному наблюдаемому?

+1

Ответ на ваш последний вопрос, да, с помощью 'Observable.Merge'. Хотя я не совсем уверен, как его применять здесь ... – supertopi

ответ

0

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

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

Единственное, что вы можете сделать, это сделать его немного лучше, делая

button.rx_tap 
    .subscribe(input) 

Вместо

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

Это неправда. Оператор 'merge' позволит вам добавить к уже запущенному наблюдаемому. – Enigmativity

+0

'merge' возвращает новое наблюдаемое, оно не может мутировать наблюдаемое. – mschumacher

+0

Да, но если вы вставляете слияние в запрос во время компиляции, вы можете вставлять значения во время выполнения. – Enigmativity