Ben Dolman
Ben Dolman

Reputation: 3205

How do I dispose inner producers in ReactiveCocoa?

Let's say I have parallel work I want to do, such as downloading multiple images. Each of these downloads is represented by a SignalProducer. I create them and flatten them using the Merge strategy. When I start the outer producer and get a disposable I expected that disposing of that would also dispose of the inner producers. What actually happens is that after disposal, my outer producer stops receiving events, but the actual work being done by the inner producers continues, because they have not been disposed.

How do I get the actual work being done by the inner producers to stop? Here's some test code that illustrates the scenario:

func producerOfValues(values: [String]) -> SignalProducer<String, NoError> {
    return SignalProducer<String, NoError> {observer, disposable in
        for value in values {
            sleep(1)
            print("doing work: \(value)")
            sendNext(observer, value)
            if disposable.disposed { // 'disposed' is never true
                print("producer disposed")
                break
            }
        }
        sendCompleted(observer)
    }
}

let (signal, sink) = SignalProducer<SignalProducer<String, NoError>, NoError>.buffer(2)
let flattened = signal.flatten(.Merge)

let letterProducer = producerOfValues(["a", "b", "c"])
let numberProducer = producerOfValues(["1", "2", "3"])

sendNext(sink, letterProducer.startOn(QueueScheduler()))
sendNext(sink, numberProducer.startOn(QueueScheduler()))
sendCompleted(sink)

let disposable = flattened.startWithNext {
    print($0)
}
disposable.dispose()

Output:

doing work: a
doing work: 1
doing work: b
doing work: 2
doing work: c
doing work: 3

Upvotes: 1

Views: 697

Answers (0)

Related Questions