Преобразовать обратные вызовы делегатов в события SignalProducer?

У меня есть объект, который является делегатом. Имеется 6 обратных вызовов делегата, информирующих делегата о состоянии дел. у меня есть MySpecialEvent быстрое перечисление, которое представляет эти состояния. Можете ли вы помочь мне понять, как правильно инициализировать SignalProducer<MySpecialEvent, NoError> и перехватить вызов делегата для продюсера next События, когда я создаю экземпляр этого объекта делегата?

Я ожидаю (поправьте меня, пожалуйста, если это не так), что производитель сигнала будет публичным producer свойство объекта делегата. Затем я могу получить ссылку на этого продюсера, передать ее и в основном обработать события в другом месте в реактивной манере.

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

ОБНОВЛЕНИЕ: я попробовал это, и это на самом деле работает.

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

1 ответ

То, что я пытаюсь сделать с функционально-реактивным программированием в целом, это как можно больше исключить использование делегатов. Вы правы, что кажется, что немного сложнее добавить MutableProperty в классе делегата. MutableProperties являются своего рода мостом между парадигмами без сохранения состояния и состояниями.

Итак, что это значит?

Вместо создания делегата для использования при обработке событий, когда все меняется. Найдите способ наблюдать за событиями как за сигналами и реагировать на события. Пример, наверное, проще всего понять.

Скажем, у вас есть модальное представление, которое вы представляете, и представляющий контроллер является делегатом представленного контроллера представления. Вы передаете нынешний контроллер модальному...

func showModal() {
  let modalVC = ModalViewController()
  modalVC.delegate = self
  self.presentModalViewController(modalVC, animated: true)
}

func modalComplete() {
  self.dismissViewControllerAnimated(true, completion: nil)
  print("All Done with Modal.")
}

Затем, представленный контроллер в какой-то момент (очевидно, не показывает все содержимое протокола делегата)

func allDone() {
  self.delegate?.modalComplete()
}

Способ FRP

Замена шаблона делегата на FRP приведет к чему-то вроде...

func showModal() {
  let modalVC = ModalViewController()
  modalVC.completionSignal
    .startWithNext { [weak self] _ in
      self.modalComplete()
    }
  self.presentModalViewController(modalVC, animated: true)
}

func modalComplete() {
  self.dismissViewControllerAnimated(true, completion: nil)
  print("All Done with the FRP Modal.")
}

И в вашем модале вы можете создать сигнал, который вы могли бы отправить, когда пришло время закрыть модал.

let (completionSignal, completionObserver) = SignalProducer<String, NoError>.buffer(1)

func allDone() {
  completionObserver.sendNext("Whatever you want")
  completionObserver.sendComplete()
}

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

Вы также можете использовать настоящий Signal а не SignalProducer определив в модальном контроллере вида как

let (completionSignal, completionObserver) = Signal<String, NoError>.pipe()

А затем просто наблюдайте за ним на родительском контроллере представления вместо того, чтобы запускать и наблюдать за ним.

Другие вопросы по тегам