#swift #reactive-cocoa #reactive-cocoa-4
#swift #реактивный-cocoa #реактивный-cocoa-4
Вопрос:
Учитывая функции multiply()
и convert()
(минимальные примеры концепции, я на самом деле планирую запрашивать удаленный сервер внутри каждой функции), каков более короткий способ реализации multiplyAndConvert()
?
// call two async functions passing the result the from the first
// as the argument to the second
multiplyAndConvert(3).startWithResult { val in
print("(val.value!)")
}
func convert(_ val: Int) -> SignalProducer<String, NSError> {
return SignalProducer<String, NSError> { observer, _ in
observer.send(value: String(val))
observer.sendCompleted()
}
}
func multiply(_ val: Int) -> SignalProducer<Int, NSError> {
return SignalProducer<Int,NSError> { observer, _ in
observer.send(value: val * 2)
observer.sendCompleted()
}
}
func multiplyAndConvert(_ val: Int) -> SignalProducer<String, NSError> {
return SignalProducer<String, NSError> { observer, _ in
multiply(val).startWithResult { res2 in
switch res2 {
case .success(let val2):
convert(val2).startWithResult { res3 in
switch res3 {
case .success(let val3):
observer.send(value:val3)
observer.sendCompleted()
case .failure(let err):
observer.send(error:err)
}
}
case .failure(let err):
observer.send(error: err)
}
observer.sendCompleted()
}
}
}
Я знаю, что должен быть более элегантный способ сделать это, но я в тупике относительно того, что это такое. Я поиграл с map, flatMap, flatten и большинством других функций, но не могу найти лучшего решения.
Ответ №1:
Используйте flatMap:
func multiplyAndConvert(_ val: Int) -> SignalProducer<String, NSError> {
return multiply(val).flatMap(.concat) { multipliedVal in
return convert(multipliedVal)
}
}
вы также можете передать convert
flatMap напрямую в качестве второго аргумента, а не закрывать его, поскольку это уже правильный тип ( Int -> SignalProducer<String, NSError>
)
multiply(val).flatMap(.concat, transform: convert)
но если convert
функция ссылается self
в вашем расширенном коде, это может привести к циклам сохранения, и в этом случае вам потребуется передать захват закрытия [weak self]
Объяснение
что flatMap
здесь делает, так это принимает ваш сигнал умножения:
-----.value(multipliedValue)-.completed
и отображает его в сигнал сигналов, используя предоставленное замыкание:
.value(convertedMultipliedValue)
/
----x-.completed
а затем «выравнивает» этот сигнал сигналов (используя .Стратегия сглаживания Concat, которая сглаживает сигнал сигналов путем объединения всех дочерних сигналов — но здесь это не имеет значения, потому что мы сглаживаем только один дочерний сигнал), чтобы дать нам:
----.value(convertedMultipliedValue)-.completed