Skip to content

Commit

Permalink
Merge pull request #2526 from NachoSoto/signal-merge
Browse files Browse the repository at this point in the history
Implemented Signal.mergeSignals. Fixes #2487
  • Loading branch information
neilpa committed Nov 17, 2015
2 parents 6f037ba + ea006fc commit 6da453a
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 1 deletion.
15 changes: 15 additions & 0 deletions ReactiveCocoa/Swift/Signal.swift
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,21 @@ extension SignalType {
}
}

extension SignalType {
/// Merges the given signals into a single `Signal` that will emit all values
/// from each of them, and complete when all of them have completed.
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
}
}

extension SignalType where Value: SignalProducerType, Error == Value.Error {
/// Returns a signal which sends all the values from producer signal emitted from
/// `signal`, waiting until each inner producer completes before beginning to
Expand Down
66 changes: 65 additions & 1 deletion ReactiveCocoaTests/Swift/SignalSpec.swift
Original file line number Diff line number Diff line change
Expand Up @@ -472,7 +472,6 @@ class SignalSpec: QuickSpec {
expect(error).to(equal(producerError))
}
}


describe("filter") {
it("should omit values from the signal") {
Expand All @@ -496,6 +495,71 @@ class SignalSpec: QuickSpec {
}
}

describe("Signal.merge") {
it("should emit values from all signals") {
let (signal1, observer1) = Signal<Int, NoError>.pipe()
let (signal2, observer2) = Signal<Int, NoError>.pipe()

let mergedSignals = Signal.merge([signal1, signal2])

var lastValue: Int?
mergedSignals.observeNext { lastValue = $0 }

expect(lastValue).to(beNil())

observer1.sendNext(1)
expect(lastValue) == 1

observer2.sendNext(2)
expect(lastValue) == 2

observer1.sendNext(3)
expect(lastValue) == 3
}

it("should not stop when one signal completes") {
let (signal1, observer1) = Signal<Int, NoError>.pipe()
let (signal2, observer2) = Signal<Int, NoError>.pipe()

let mergedSignals = Signal.merge([signal1, signal2])

var lastValue: Int?
mergedSignals.observeNext { lastValue = $0 }

expect(lastValue).to(beNil())

observer1.sendNext(1)
expect(lastValue) == 1

observer1.sendCompleted()
expect(lastValue) == 1

observer2.sendNext(2)
expect(lastValue) == 2
}

it("should complete when all signals complete") {
let (signal1, observer1) = Signal<Int, NoError>.pipe()
let (signal2, observer2) = Signal<Int, NoError>.pipe()

let mergedSignals = Signal.merge([signal1, signal2])

var completed = false
mergedSignals.observeCompleted { completed = true }

expect(completed) == false

observer1.sendNext(1)
expect(completed) == false

observer1.sendCompleted()
expect(completed) == false

observer2.sendCompleted()
expect(completed) == true
}
}

describe("ignoreNil") {
it("should forward only non-nil values") {
let (signal, observer) = Signal<Int?, NoError>.pipe()
Expand Down

0 comments on commit 6da453a

Please sign in to comment.