Combine: Getting Started |

Learn how to use Combine’s Publisher and Subscriber to handle event streams, merge multiple publishers and more.

This is a companion discussion topic for the original entry at

thanks, great article, just want to double I check I follow correctly, in stopGame by adding this

subscriptions.forEach { $0.cancel() }

you don’t need anymore the second line ?



The gameTimer property isn’t stored into the subscriptions Set, so you need to cancel it with gameTimer?.cancel() method.

By calling the subscriptions.forEach { $0.cancel() } method you will cancel all the subscriptions created for getting random images and downloading them.

your right, sorry my mistake!

Don’t worry! You’re welcome :wink:

Handy article.

Could you please elaborate why the start of the closure expression within the below operator for the download() method is different to the randomImage() method?
.tryMap { response -> Data in

Omission of -> Data results in a Generic parameter ‘T’ could not be inferred error.
If both the publishers from URLSession return (data: Data, response: URLResponse), why do they need to be processed differently?

Both the tryMap operators on the download() and the randomImage() functions do the same things, can you please elaborate on it?

From my understanding, you are explicitly specifying Data as being the return type in the closure to tryMap for the download() method, but are not doing to same for the randomImage() method. As you’ve stated, those two functions perform the same action, for which reason I was curious about the above discrepancy.

Both the first tryMap on donwload(url:) and randomImage(url:) does the same thing. The second tryMap on download(url:) converts the received Data into a valid UIImage.

The reason is that if you add just one tryMap the compiler can infer the return type, otherwise not.
For example, try to remove the return type on randomImage(url:), in this case, you will not get any error because the compiler can infer the return type.
Otherwise, if you try to remove the return type on the first tryMap on the download(url:) function you will get an error because the second tryMap needs to explicitly know what’s the input type.

This is what I want to ask too, thanks for the explanation.

In Refining the App section, would you mind to explain more about .store(in: &subscriptions) like what it does and why it is doing it. Doesn’t AnyCancellable would call the .cancel() automatically?

I don’t understand why we need to remove subscribers manually? We didn’t do that in randomImage() or download(). Because we used Timer.publish() this time, so we need to add the logic on cancel() manually, am I right?

Right, that explains it. Thank you!

Hi Thank you for the article. When I played the game, I encountered many times which all four images are same (first, second images are randomly same) for this case, how do we identify in the completion handler and initial a new publisher? I am not sure how we can make it recreated one until it’s not the same

Hi thegodland! It happens sometimes, you can try with a flatMap to throw an error and to get a new UIImage if the first and the second images are equal.

Hi Fabrizio

Thank you for this wonderful article.
I have a question here. I am able to understand how the Publisher Subscriber model works.
But I am quite confused as to where are those methods depicted in the diagram like * subscribe, receive(subscription:), receive(_:), receive(completion:) implemented? I understand these are the methods of Publisher protocol. So does that mean the dataTaskPublisher or Timer Publisher classes would have those implementations.

Please clarify. Thank You.

Hi @shrutisharma, those dataTaskPublisher and TimerPublisher are both Publishers so, yes they have receive(subscription:), receive(_:), receive(completion:) methods. We used other methods to get values from those Publishers, like tryMap.
We also used sink(receiveCompletion:, receiveValue:) that is called at every sent value and once the Publisher has finished sending values.