Skip to content

Instantly share code, notes, and snippets.

@swhitty
Last active May 6, 2021 02:18
Show Gist options
  • Save swhitty/4122dfe5026080e10bcc54fb13d31077 to your computer and use it in GitHub Desktop.
Save swhitty/4122dfe5026080e10bcc54fb13d31077 to your computer and use it in GitHub Desktop.
import Combine
extension Publisher where Failure == Never {
/// Converts a publisher into a `Driver`
func driver() -> Driver<Output> { Driver(self) }
}
extension Driver {
func driver() -> Driver<Output> { self }
}
/// Publisher that is useful to drive the user interface;
/// - Always returns values on main thread.
/// - All subscribers share the upstream publisher
/// - Is stateful, upon subscription the most recent value is always replayed (if available).
///
/// Inspired by the RxCocoa implementation;
/// https://github.com/ReactiveX/RxSwift/blob/main/RxCocoa/Traits/Driver/Driver.swift
///
struct Driver<Output>: Publisher {
typealias Failure = Never
private let publisher: AnyPublisher<Output, Never>
init<P>(_ upstream: P) where P: Publisher, P.Output == Output, P.Failure == Never {
self.publisher = upstream
.map(Optional.some)
.multicast { CurrentValueSubject<Output?, Failure>(.none) }
.autoconnect()
.compactMap { $0 }
.receive(on: DispatchQueue.main)
.eraseToAnyPublisher()
}
func receive<S>(subscriber: S) where S: Subscriber, S.Input == Output, S.Failure == Failure {
publisher.receive(subscriber: subscriber)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment