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 https://www.raywenderlich.com/7864801-combine-getting-started
Learn how to use Combine’s Publisher and Subscriber to handle event streams, merge multiple publishers and more.
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 ?
gameTimer?.cancel()
Thanks!
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
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 Publisher
s, like tryMap
.
We also used sink(receiveCompletion:, receiveValue:)
that is called at every sent value and once the Publisher
has finished sending values.