In my setup, I have a GridView
that consists of many GridViewCell
s. Each cell has a UITapGestureRecognizer
.
For convenience, the GridView
has the following function
func cellsTapGestureRecognizers() -> [UITapGestureRecognizer?]
which returns the UITapGestureRecognizer
s of all its cells (if they exist).
In the UIViewController
, that uses the GridView
, my goal is to treat the taps as Signal
s. I managed to do this but with the limitation that I create one Signal
for each GridViewCell
which seems unnecessary.
func createTapSignals() -> [Signal<Position, NoError>?] {
var signals: [Signal<Position, NoError>] = []
for maybeTap in self.gridView.cellsTapGestureRecognizers() {
if let tap = maybeTap {
let signal = tap.gestureSignalView()
.map { $0 as! GridViewCell }
.map {$0.position}
signals.append(signal)
}
}
return signals
}
Is it possible to merge all the signals that are created in createTapSignals()
such that in the end there is only one signal left of type Signal<Position, NoError>
?
I looked into the documentation, but only found the way how to merge SignalProducers
by using flatten(.Merge)
. Is there a similar approach I can take to merge an Array
of Signal
s.
Note that gestureSignalView()
which is used in the function above returns a Signal<UIView, NoError>
that carries the UIView
of the UITapGestureRecognizer
(inspired by @NachoSoto's gist).
I found the solution myself after searching around in the RAC Github repo.
The (static) function merge
was exactly was I was looking for. It's part of the SignalType
protocol (which Signal
conforms to) and is implemented in a protocol extension.
So, I can just do the following:
let signals = createTapSignals()
let mergedSignal = Signal.merge(signals)
For reference, here is how merge
is implemented:
public static func merge<S: SequenceType where S.Generator.Element == Signal<Value, Error>>(signals: S) -> Signal<Value, Error> {
let producer = SignalProducer<Signal<Value, Error>, Error>(values: signals)
var result: Signal<Value, Error>!
producer.startWithSignal { (signal, _) in
result = signal.flatten(.Merge)
}
return result
}