Skip to content

Commit b94aa79

Browse files
authored
Merge pull request #2462 from onevcat/fix/async-modifier-start-callback-order
Call async modifier start callback before resume
2 parents d0f6fa2 + 316c824 commit b94aa79

File tree

1 file changed

+15
-12
lines changed

1 file changed

+15
-12
lines changed

Sources/Networking/ImageDownloader.swift

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -423,12 +423,14 @@ open class ImageDownloader: @unchecked Sendable {
423423

424424
private func startDownloadTask(
425425
context: DownloadingContext,
426-
callback: SessionDataTask.TaskCallback
426+
callback: SessionDataTask.TaskCallback,
427+
beforeTaskResume: ((DownloadTask) -> Void)? = nil
427428
) -> DownloadTask
428429
{
429430
let downloadTask = addDownloadTask(context: context, callback: callback)
430431

431432
guard let sessionTask = downloadTask.sessionTask, !sessionTask.started else {
433+
beforeTaskResume?(downloadTask)
432434
return downloadTask
433435
}
434436

@@ -468,6 +470,10 @@ open class ImageDownloader: @unchecked Sendable {
468470
}
469471
}
470472

473+
// Ensure `beforeTaskResume` runs before `resume()`. Some stubbing layers may complete the request
474+
// synchronously during `resume()`, so any "task started" callback should be invoked before that.
475+
beforeTaskResume?(downloadTask)
476+
471477
reportWillDownloadImage(url: context.url, request: context.request)
472478
sessionTask.resume()
473479
return downloadTask
@@ -493,18 +499,15 @@ open class ImageDownloader: @unchecked Sendable {
493499
createDownloadContext(with: url, options: options) { result in
494500
switch result {
495501
case .success(let context):
496-
// `downloadTask` will be set if the downloading started immediately. This is the case when no request
497-
// modifier or a sync modifier (`ImageDownloadRequestModifier`) is used. Otherwise, when an
498-
// `AsyncImageDownloadRequestModifier` is used the returned `downloadTask` of this method will be `nil`
499-
// and the actual "delayed" task is given in `AsyncImageDownloadRequestModifier.onDownloadTaskStarted`
500-
// callback.
501-
let actualDownloadTask = self.startDownloadTask(
502-
context: context,
503-
callback: self.createTaskCallback(completionHandler, options: options)
504-
)
505-
downloadTask.linkToTask(actualDownloadTask)
502+
let taskCallback = self.createTaskCallback(completionHandler, options: options)
506503
if let modifier = options.requestModifier {
507-
modifier.onDownloadTaskStarted?(downloadTask)
504+
_ = self.startDownloadTask(context: context, callback: taskCallback, beforeTaskResume: { actualDownloadTask in
505+
downloadTask.linkToTask(actualDownloadTask)
506+
modifier.onDownloadTaskStarted?(downloadTask)
507+
})
508+
} else {
509+
let actualDownloadTask = self.startDownloadTask(context: context, callback: taskCallback)
510+
downloadTask.linkToTask(actualDownloadTask)
508511
}
509512
case .failure(let error):
510513
options.callbackQueue.execute {

0 commit comments

Comments
 (0)