Requirements: iOS 13.0+ / macOS 10.15+ / tvOS 13.0+ / watchOS 6.0+ • Swift 5.8+ / Xcode 14.3+
Combine publishers can publish any number of values, at any time, before they complete. It is particularly the case of AnyPublisher, frequently returned by our frameworks or applications.
When we deal with publishers that are expected to publish their values according to a specific pattern, it is easy to neglect edge cases such as late publishing, early completion, too many published values, etc. And quite often, the behavior of such publishers is subject to interpretation, imprecise documentation, or buggy implementations.
This library provides compiler-checked definition, and subscription, to publishers that conform to specific traits:
-
Single Publishers publish exactly one value, or an error.
The Combine
Just
,Future
andURLSession.DataTaskPublisher
are examples of such publishers.--------> can never publish anything, never complete. -----x--> can fail before publishing any value. --o--|--> can publish one value and complete.
-
Maybe Publishers publish exactly zero value, or one value, or an error:
The Combine
Empty
,Just
,Future
andURLSession.DataTaskPublisher
are examples of such publishers.--------> can never publish anything, never complete. -----x--> can fail before publishing any value. -----|--> can complete without publishing any value. --o--|--> can publish one value and complete.
-
Immediate Publishers publish a value or fail, right on subscription:
The Combine
Just
andFail
are examples of such publishers.x-------> can fail immediately. o - - - > can publish one value immediately (and then publish any number of values, at any time, until the eventual completion).
Derived Tools
- Trait Operators
- SinglePublisherOperation
- TraitPublishers.AsOperation
- TraitPublishers.Maybe
- TraitPublishers.PreventCancellation
- TraitPublishers.Single
- TraitPublishers.ZipSingle
- TraitSubscriptions.Maybe
- TraitSubscriptions.Single
CombineTraits preserves the general ergonomics of Combine. Your application still deals with regular Combine publishers and operators.
AnyPublisher
can be replaced with AnySinglePublisher
, AnyMaybePublisher
, or AnyImmediatePublisher
, in order to express which trait a publisher conforms to:
func refreshPublisher() -> AnySinglePublisher<Void, Error> {
downloadPublisher()
.map { apiModel in Model(apiModel) }
.flatMap { model in savePublisher(model) }
.eraseToAnySinglePublisher()
}
On the consumption side, sink
can be replaced with sinkSingle
or sinkMaybe
, for easier handling of a given publisher trait:
let cancellable = refreshPublisher().sinkSingle { result in
switch result {
case .success: ...
case let .failure(error): ...
}
}