mirror of
https://github.com/zhigang1992/Kingfisher.git
synced 2026-04-30 13:02:33 +08:00
Expose the receive response delegate
This commit is contained in:
@@ -88,6 +88,10 @@ public enum KingfisherError: Error {
|
||||
/// The task is done but no URL response found. Code 2005.
|
||||
/// - task: The failed task.
|
||||
case noURLResponse(task: SessionDataTask)
|
||||
|
||||
/// The task is cancelled by `ImageDownloaderDelegate` due to the `.cancel` response disposition is
|
||||
/// specified by the delegate method. Code 2006.
|
||||
case cancelledByDelegate(response: URLResponse)
|
||||
}
|
||||
|
||||
/// Represents the error reason during Kingfisher caching system.
|
||||
@@ -345,7 +349,10 @@ extension KingfisherError.ResponseErrorReason {
|
||||
case .dataModifyingFailed(let task):
|
||||
return "The data modifying delegate returned `nil` for the downloaded data. Task: \(task)."
|
||||
case .noURLResponse(let task):
|
||||
return "No URL response received. Task: \(task),"
|
||||
return "No URL response received. Task: \(task)."
|
||||
case .cancelledByDelegate(let response):
|
||||
return "The downloading task is cancelled by the downloader delegate. Response: \(response)."
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -356,6 +363,7 @@ extension KingfisherError.ResponseErrorReason {
|
||||
case .URLSessionError: return 2003
|
||||
case .dataModifyingFailed: return 2004
|
||||
case .noURLResponse: return 2005
|
||||
case .cancelledByDelegate: return 2006
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -184,6 +184,9 @@ open class ImageDownloader {
|
||||
sessionDelegate.onValidStatusCode.delegate(on: self) { (self, code) in
|
||||
return (self.delegate ?? self).isValidStatusCode(code, for: self)
|
||||
}
|
||||
sessionDelegate.onResponseReceived.delegate(on: self) { (self, invoke) in
|
||||
(self.delegate ?? self).imageDownloader(self, didReceive: invoke.0, completionHandler: invoke.1)
|
||||
}
|
||||
sessionDelegate.onDownloadingFinished.delegate(on: self) { (self, value) in
|
||||
let (url, result) = value
|
||||
do {
|
||||
|
||||
@@ -116,6 +116,28 @@ public protocol ImageDownloaderDelegate: AnyObject {
|
||||
/// - Note: If the default 200 to 400 valid code does not suit your need,
|
||||
/// you can implement this method to change that behavior.
|
||||
func isValidStatusCode(_ code: Int, for downloader: ImageDownloader) -> Bool
|
||||
|
||||
/// Called when the task has received a valid HTTP response after it passes other checks such as the status code.
|
||||
/// You can perform additional checks or verification on the response to determine if the download should be allowed.
|
||||
///
|
||||
/// For example, it is useful if you want to verify some header values in the response before actually starting the
|
||||
/// download.
|
||||
///
|
||||
/// If implemented, it is your responsibility to call the `completionHandler` with a proper response disposition,
|
||||
/// such as `.allow` to start the actual downloading or `.cancel` to cancel the task. If `.cancel` is used as the
|
||||
/// disposition, the downloader will raise an `KingfisherError` with
|
||||
/// `ResponseErrorReason.cancelledByDelegate` as its reason. If not implemented, any response which passes other
|
||||
/// checked will be allowed and the download starts.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - downloader: The `ImageDownloader` object which is used for the downloading operation.
|
||||
/// - response: The original response object of the downloading process.
|
||||
/// - completionHandler: A completion handler that receives the disposition for the download task. You must call
|
||||
/// this handler with either `.allow` or `.cancel`.
|
||||
func imageDownloader(
|
||||
_ downloader: ImageDownloader,
|
||||
didReceive response: URLResponse,
|
||||
completionHandler: @escaping (URLSession.ResponseDisposition) -> Void)
|
||||
}
|
||||
|
||||
// Default implementation for `ImageDownloaderDelegate`.
|
||||
@@ -151,4 +173,12 @@ extension ImageDownloaderDelegate {
|
||||
public func imageDownloader(_ downloader: ImageDownloader, didDownload data: Data, for url: URL) -> Data? {
|
||||
return data
|
||||
}
|
||||
|
||||
public func imageDownloader(
|
||||
_ downloader: ImageDownloader,
|
||||
didReceive response: URLResponse,
|
||||
completionHandler: @escaping (URLSession.ResponseDisposition) -> Void) {
|
||||
completionHandler(.allow)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -47,6 +47,7 @@ open class SessionDelegate: NSObject {
|
||||
private let lock = NSLock()
|
||||
|
||||
let onValidStatusCode = Delegate<Int, Bool>()
|
||||
let onResponseReceived = Delegate<(URLResponse, (URLSession.ResponseDisposition) -> Void), Void>()
|
||||
let onDownloadingFinished = Delegate<(URL, Result<URLResponse, KingfisherError>), Void>()
|
||||
let onDidDownloadData = Delegate<SessionDataTask, Data?>()
|
||||
|
||||
@@ -169,7 +170,15 @@ extension SessionDelegate: URLSessionDataDelegate {
|
||||
completionHandler(.cancel)
|
||||
return
|
||||
}
|
||||
completionHandler(.allow)
|
||||
|
||||
let inspectedHandler: (URLSession.ResponseDisposition) -> Void = { disposition in
|
||||
if disposition == .cancel {
|
||||
let error = KingfisherError.responseError(reason: .cancelledByDelegate(response: response))
|
||||
self.onCompleted(task: dataTask, result: .failure(error))
|
||||
}
|
||||
completionHandler(disposition)
|
||||
}
|
||||
onResponseReceived.call((response, inspectedHandler))
|
||||
}
|
||||
|
||||
open func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
|
||||
|
||||
Reference in New Issue
Block a user