-
Notifications
You must be signed in to change notification settings - Fork 318
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Replace legacy image downloader with new actor-based implementation (#…
…4588) * Replace legacy image downloader with new actor-based implementation * Remove failed tasks from inflightRequests array * add changelog entry * small refactoring
- Loading branch information
1 parent
ce064ed
commit c976919
Showing
17 changed files
with
164 additions
and
532 deletions.
There are no files selected for viewing
This file contains 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
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
47 changes: 47 additions & 0 deletions
47
Sources/MapboxNavigation/ImageDownloader/ImageDownloader.swift
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
import Foundation | ||
|
||
enum DownloadError: Error { | ||
case serverError | ||
case clientError | ||
case noImageData | ||
} | ||
|
||
@available(iOS 13.0, *) | ||
actor ImageDownloader: ImageDownloaderProtocol { | ||
private let urlSession: URLSession | ||
|
||
private var inflightRequests: [URL: Task<CachedURLResponse, Error>] = [:] | ||
|
||
init(configuration: URLSessionConfiguration? = nil) { | ||
let defaultConfiguration = URLSessionConfiguration.default | ||
defaultConfiguration.urlCache = URLCache(memoryCapacity: 5 * 1024 * 1024, diskCapacity: 20 * 1024 * 1024) | ||
self.urlSession = URLSession(configuration: configuration ?? defaultConfiguration) | ||
} | ||
|
||
nonisolated func download(with url: URL, completion: @escaping (Result<CachedURLResponse, Error>) -> Void) { | ||
Task { | ||
do { | ||
let response = try await self.fetch(url) | ||
completion(.success(response)) | ||
} catch { | ||
completion(.failure(error)) | ||
} | ||
} | ||
} | ||
|
||
private func fetch(_ url: URL) async throws -> CachedURLResponse { | ||
if let inflightTask = inflightRequests[url] { | ||
return try await inflightTask.value | ||
} | ||
|
||
let downloadTask = Task<CachedURLResponse, Error> { | ||
let (data, response) = try await urlSession.data(from: url) | ||
return CachedURLResponse(response: response, data: data) | ||
} | ||
|
||
inflightRequests[url] = downloadTask | ||
defer { inflightRequests[url] = nil } | ||
|
||
return try await downloadTask.value | ||
} | ||
} |
5 changes: 5 additions & 0 deletions
5
Sources/MapboxNavigation/ImageDownloader/ImageDownloaderProtocol.swift
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import Foundation | ||
|
||
protocol ImageDownloaderProtocol { | ||
func download(with url: URL, completion: @escaping (Result<CachedURLResponse, Error>) -> Void) | ||
} |
22 changes: 22 additions & 0 deletions
22
Sources/MapboxNavigation/ImageDownloader/LegacyImageDownloader.swift
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import Foundation | ||
|
||
@available(iOS, deprecated: 13.0, message: "Use ImageDownloader instead.") | ||
final class LegacyImageDownloader: ImageDownloaderProtocol { | ||
private let urlSession: URLSession | ||
|
||
init(configuration: URLSessionConfiguration? = nil) { | ||
let defaultConfiguration = URLSessionConfiguration.default | ||
defaultConfiguration.urlCache = URLCache(memoryCapacity: 5 * 1024 * 1024, diskCapacity: 20 * 1024 * 1024, diskPath: nil) | ||
self.urlSession = URLSession(configuration: configuration ?? defaultConfiguration) | ||
} | ||
|
||
func download(with url: URL, completion: @escaping (Result<CachedURLResponse, Error>) -> Void) { | ||
urlSession.dataTask(with: URLRequest(url)) { data, response, error in | ||
if let response, let data { | ||
completion(.success(CachedURLResponse(response: response, data: data))) | ||
} else if let error { | ||
completion(.failure(error)) | ||
} | ||
}.resume() | ||
} | ||
} |
Oops, something went wrong.