CombineDriver

Drivers are Publishers which don’t complete. CombineDriver is a small library which implements them for Apple’s Combine.

Motivation:

Some data sources like user input do not logically ‘complete’ and modelling them with that in mind is semantically correct and sometimes practically preferable.

In particular the ‘driving’ logic in an application is often written assuming it will be robust to error states and will never finish on its own. suppressFinishToAnyDriver() enforces the lack of error states and prevents completion.

Usage

  • Include the library via Swift Package Manager.
  • Import CombineDriver
  • Call suppressFinishToAnyDriver() on a Publisher of failure type Never to receive an AnyDriver which has the aforementioned properties.
  • If desired:
    • Use suppressFailureAndFinishToAnyDriver() to also ignore failures from a Publisher.
    • Use PassthroughDrivingSubject and CurrentValueDrivingSubject as alternatives to the native Combine Subjects.

Implementation:

The underlying implementation is simple:

extension Publisher {
    /// suppressFailure prevents failures from emitting to subscribers.
    func suppressFailure()
    -> Publishers.CompactMap<Publishers.ReplaceError<Publishers.Map<Self, Self.Output?>>, Self.Output>
    {
        self
            .map { Optional($0) }
            .replaceError(with: nil)
            .compactMap { $0 }
    }

    /// suppressCompletion prevents a completion from emitting to subscribers.
    func suppressCompletion()
    -> Publishers.FlatMap<Self, Publishers.SetFailureType<Publishers.Concatenate<Publishers.Sequence<[()], Never>, Empty<(), Never>>, Self.Failure>>
    {
        Empty(completeImmediately: false)
            .prepend(())
            .setFailureType(to: Failure.self)
            .flatMap {
                self
            }
    }
}

Future Improvements:

Convenience wrappers around use input sources in UIKit would probably be nice!

Contributions and super welcome.

GitHub

View Github