diff --git a/Sources/Networking/ImageDownloader.swift b/Sources/Networking/ImageDownloader.swift index e3e9ba0a3..b89e0f90e 100644 --- a/Sources/Networking/ImageDownloader.swift +++ b/Sources/Networking/ImageDownloader.swift @@ -164,7 +164,13 @@ open class ImageDownloader { authenticationChallengeResponder = self setupSessionHandler() } - + + /// You could set the extra handler before a downloading task starts. + public var extraSessionDelegateHandler:URLSessionDataDelegate? { + set {sessionDelegate.extraHandler = newValue} + get {return sessionDelegate.extraHandler} + } + deinit { session.invalidateAndCancel() } private func setupSessionHandler() { diff --git a/Sources/Networking/SessionDelegate.swift b/Sources/Networking/SessionDelegate.swift index 8a9b75cb0..e637e1e32 100644 --- a/Sources/Networking/SessionDelegate.swift +++ b/Sources/Networking/SessionDelegate.swift @@ -45,6 +45,7 @@ class SessionDelegate: NSObject { private var tasks: [URL: SessionDataTask] = [:] private let lock = NSLock() + weak var extraHandler: URLSessionDataDelegate? let onValidStatusCode = Delegate() let onDownloadingFinished = Delegate<(URL, Result), Void>() @@ -145,6 +146,7 @@ class SessionDelegate: NSObject { lock.unlock() task?.forceCancel() } + } extension SessionDelegate: URLSessionDataDelegate { @@ -259,4 +261,43 @@ extension SessionDelegate: URLSessionDataDelegate { remove(sessionTask) sessionTask.onTaskDone.call((result, sessionTask.callbacks)) } + + + // MARK: - extraHandler + @available(iOS 7.0, OSX 11.0, tvOS 9.0, watchOS 2.0, *) + func urlSessionDidFinishEvents(forBackgroundURLSession session: URLSession) { + extraHandler?.urlSessionDidFinishEvents?(forBackgroundURLSession: session) + } + func urlSession(_ session: URLSession, didBecomeInvalidWithError error: Error?) { + extraHandler?.urlSession?(session, didBecomeInvalidWithError: error) + } + @available(iOS 11.0, OSX 10.13, tvOS 11.0, watchOS 4.0, *) + func urlSession(_ session: URLSession, taskIsWaitingForConnectivity task: URLSessionTask) { + extraHandler?.urlSession?(session, taskIsWaitingForConnectivity: task) + } + @available(iOS 10.0, OSX 10.12, tvOS 10.0, watchOS 3.0, *) + func urlSession(_ session: URLSession, task: URLSessionTask, didFinishCollecting metrics: URLSessionTaskMetrics) { + extraHandler?.urlSession?(session, task: task, didFinishCollecting: metrics) + } + @available(iOS 9.0, OSX 10.11, tvOS 9.0, watchOS 2.0, *) + func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didBecome streamTask: URLSessionStreamTask) { + extraHandler?.urlSession?(session, dataTask: dataTask, didBecome: streamTask) + } + func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didBecome downloadTask: URLSessionDownloadTask) { + extraHandler?.urlSession?(session, dataTask: dataTask, didBecome: downloadTask) + } + func urlSession(_ session: URLSession, task: URLSessionTask, needNewBodyStream completionHandler: @escaping (InputStream?) -> Void) { + extraHandler?.urlSession?(session, task: task, needNewBodyStream: completionHandler) + } + func urlSession(_ session: URLSession, task: URLSessionTask, didSendBodyData bytesSent: Int64, totalBytesSent: Int64, totalBytesExpectedToSend: Int64) { + extraHandler?.urlSession?(session, task: task, didSendBodyData: bytesSent, totalBytesSent: totalBytesSent, totalBytesExpectedToSend: totalBytesExpectedToSend) + } + func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, willCacheResponse proposedResponse: CachedURLResponse, completionHandler: @escaping (CachedURLResponse?) -> Void) { + extraHandler?.urlSession?(session, dataTask: dataTask, willCacheResponse: proposedResponse, completionHandler: completionHandler) + } + @available(iOS 11.0, OSX 10.13, tvOS 11.0, watchOS 4.0, *) + func urlSession(_ session: URLSession, task: URLSessionTask, willBeginDelayedRequest request: URLRequest, completionHandler: @escaping (URLSession.DelayedRequestDisposition, URLRequest?) -> Void) { + extraHandler?.urlSession?(session, task: task, willBeginDelayedRequest: request, completionHandler: completionHandler) + } + } diff --git a/Tests/KingfisherTests/ImageDownloaderTests.swift b/Tests/KingfisherTests/ImageDownloaderTests.swift index 88ab610c6..63c9e0b8e 100644 --- a/Tests/KingfisherTests/ImageDownloaderTests.swift +++ b/Tests/KingfisherTests/ImageDownloaderTests.swift @@ -32,6 +32,7 @@ class ImageDownloaderTests: XCTestCase { var downloader: ImageDownloader! var modifier = URLModifier() + var expectation: XCTestExpectation? override class func setUp() { super.setUp() @@ -547,6 +548,18 @@ class ImageDownloaderTests: XCTestCase { XCTAssertEqual(task?.sessionTask.task.priority, URLSessionTask.highPriority) waitForExpectations(timeout: 3, handler: nil) } + + func testExtraSessionDelegateHandler() { + expectation = expectation(description: #function) + + downloader.extraSessionDelegateHandler = self + let url = testURLs[0] + stub(url, data: testImageData) + + downloader.downloadImage(with: url) + waitForExpectations(timeout: 3, handler: nil) + } + } extension ImageDownloaderTests: ImageDownloaderDelegate { @@ -576,3 +589,9 @@ class AsyncURLModifier: AsyncImageDownloadRequestModifier { } } } + +extension ImageDownloaderTests: URLSessionDataDelegate { + func urlSession(_ session: URLSession, task: URLSessionTask, didFinishCollecting metrics: URLSessionTaskMetrics) { + expectation?.fulfill() + } +}