Преобразовать обратные вызовы делегатов в события 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()
А затем просто наблюдайте за ним на родительском контроллере представления вместо того, чтобы запускать и наблюдать за ним.