Forked from danielctull/DownloadTaskPublisher.swift
Created
February 14, 2022 08:04
-
-
Save seanlilmateus/eca250c99c488dcf9608f2adc3ca4cb8 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Combine | |
extension URLSession { | |
/// Returns a publisher that wraps a URL session download task for a given | |
/// URL. | |
/// | |
/// - Parameter url: The URL for which to create a download task. | |
/// - Returns: A publisher that wraps a download task for the URL. | |
public func downloadTaskPublisher(for url: URL) -> DownloadTaskPublisher { | |
DownloadTaskPublisher(session: self, request: URLRequest(url: url)) | |
} | |
/// Returns a publisher that wraps a URL session download task for a given | |
/// URL request. | |
/// | |
/// - Parameter request: The URL request for which to create a download task. | |
/// - Returns: A publisher that wraps a download task for the URL request. | |
public func downloadTaskPublisher(for request: URLRequest) -> DownloadTaskPublisher { | |
DownloadTaskPublisher(session: self, request: request) | |
} | |
} | |
public struct DownloadTaskPublisher { | |
fileprivate let session: URLSession | |
fileprivate let request: URLRequest | |
} | |
extension DownloadTaskPublisher: Publisher { | |
public typealias Output = (URL, URLResponse) | |
public typealias Failure = Error | |
public func receive<Subscriber>(subscriber: Subscriber) | |
where | |
Subscriber: Combine.Subscriber, | |
Subscriber.Failure == Failure, | |
Subscriber.Input == Output | |
{ | |
let subscription = Subscription(subscriber: subscriber, session: session, request: request) | |
subscriber.receive(subscription: subscription) | |
} | |
} | |
extension DownloadTaskPublisher { | |
fileprivate final class Subscription { | |
private let downloadTask: URLSessionDownloadTask | |
init<Subscriber>(subscriber: Subscriber, session: URLSession, request: URLRequest) | |
where | |
Subscriber: Combine.Subscriber, | |
Subscriber.Input == Output, | |
Subscriber.Failure == Failure | |
{ | |
downloadTask = session.downloadTask(with: request, completionHandler: { (url, response, error) in | |
guard let url = url, let response = response else { | |
subscriber.receive(completion: .failure(error!)) | |
return | |
} | |
_ = subscriber.receive((url, response)) | |
subscriber.receive(completion: .finished) | |
}) | |
} | |
} | |
} | |
extension DownloadTaskPublisher.Subscription: Subscription { | |
fileprivate func request(_ demand: Subscribers.Demand) { | |
downloadTask.resume() | |
} | |
fileprivate func cancel() { | |
downloadTask.cancel() | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment