Skip to content

Instantly share code, notes, and snippets.

@erenkabakci
Last active February 20, 2020 16:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save erenkabakci/2cbdef52e9a821029e77513222f20349 to your computer and use it in GitHub Desktop.
Save erenkabakci/2cbdef52e9a821029e77513222f20349 to your computer and use it in GitHub Desktop.
PublishersPlayground
import Combine
import Foundation
struct SomeError: Error {}
// 1- Subject scenarios
let currentValueSubject = CurrentValueSubject<String, Error>("foo")
let passThroughSubject = PassthroughSubject<String, Error>()
currentValueSubject.send("Loo") // receiveValue of the subscriber will be called when "sink", receiveCompletion won't be called, the subscription is still active
passThroughSubject.send("Loo") // receiveValue of the subscriber will be called if "sink" before this line, receiveCompletion won't be called, the subscription is still active
currentValueSubject.send(completion: .finished) // receiveValue won't be called, receiveCompletion will be called with finish, the subscription and "sink" terminates
passThroughSubject.send(completion: .finished) // receiveValue won't be called, receiveCompletion will be called with finish, the subscription and "sink" terminates
// -------- you can send once completion only, either .finished or .failure, after that the subscription terminates --------
currentValueSubject.send(completion: .failure(SomeError())) // receiveValue won't be called, receiveCompletion will be called with failure, the subscription and "sink" terminates
passThroughSubject.send(completion: .failure(SomeError())) // receiveValue won't be called, receiveCompletion will be called with failure, the subscription and "sink" terminates
// 2- Publisher scenarios
var publisher: AnyPublisher<String, Error>
var publisherNeverError: AnyPublisher<String, Never>
var publisherNeverValue: AnyPublisher<Never, Error>
var publisherNeverValueNeverError: AnyPublisher<Never, Never>
// 2a- ------ Publishers which are possible for asignments to <String, Error> -------
publisher = currentValueSubject.eraseToAnyPublisher() // receiveValue of the subscriber will be called immediately when "sink", receiveCompletion won't be called, the subscription is still active
publisher = passThroughSubject.eraseToAnyPublisher() // receiveValue of the subscriber will be called if "sink" is before this line, receiveCompletion won't be called, the subscription is still active
publisher = Future<String, Error> { promise in
promise(.success("Foo"))
}.eraseToAnyPublisher() // receiveValue will be called immediately when "sink", receiveCompletion will also be called right after, with .finished, the subscription is terminated
publisher = Future<String, Error> { promise in
promise(.failure(NSError()))
}.eraseToAnyPublisher() // receiveValue won't be called, receiveCompletion will be called with .failure, the subscription is terminated
// 2b- ------ Publishers possible for <String, Never> assignments -------
publisherNeverError = Just("Foo").eraseToAnyPublisher() // receiveValue will be called immediately when "sink", receiveCompletion won't be called, the subscription is still active
publisherNeverError = Empty(completeImmediately: true).eraseToAnyPublisher() // receiveValue won't be called, receiveCompletion will be called with finish, the subscription and "sink" terminates
publisherNeverError = currentValueSubject.replaceError(with: "Boo").eraseToAnyPublisher() // receiveValue will be called immediately with the value "Boo" when "sink", receiveCompletion won't be called, the subscription is still active
publisherNeverError = passThroughSubject.replaceError(with: "Boo").eraseToAnyPublisher() // receiveValue will be called if "sink" is before this line, receiveCompletion won't be called, the subscription is still active
// 2c- ------ Publishers possible for <Never, Error> assignments --------
publisherNeverValue = currentValueSubject.ignoreOutput().eraseToAnyPublisher()
currentValueSubject.send(completion: .finished) // receiveValue won't be called since the output is ignored, receiveCompletion will be called with .finished, the subscription and "sink" terminates
publisherNeverValue = passThroughSubject.ignoreOutput().eraseToAnyPublisher()
passThroughSubject.send(completion: .failure(SomeError())) // receiveValue won't be called since the output is ignored, receiveCompletion will be called with .failure, the subscription and "sink" terminates
publisherNeverValue = Fail(error: SomeError()).eraseToAnyPublisher() // receiveValue won't be called, receiveCompletion will be called with .failure, the subscription and "sink" terminates
// 2d- ------ Publishers possible for <Never, Never> assignments --------
// This is a very rare scenario since why would you want a stream which never receives a value but also never error. So the only possibility is to receiveCompletion with .finished
// In this case any subject with sendCompletion or Future.ignoreOutput would do it.
publisherNeverValueNeverError = Future<String, Error> { promise in
promise(.success("Foo"))
}
.catch { _ in Just("Foo") }
.ignoreOutput()
.eraseToAnyPublisher()
// Other publisher scenarios
let _ = Empty<String, Error>() // never receives value, never completes, subscription is always active, open stream forever!
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment