-
Notifications
You must be signed in to change notification settings - Fork 314
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
- Loading branch information
1 parent
ce064ed
commit f3f3edc
Showing
16 changed files
with
163 additions
and
532 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
5 changes: 5 additions & 0 deletions
5
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,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() | ||
} | ||
} |
47 changes: 47 additions & 0 deletions
47
Sources/MapboxNavigation/ImageDownloader/ModernImageDownloader.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 | ||
let response = try await downloadTask.value | ||
inflightRequests[url] = nil | ||
|
||
return response | ||
} | ||
} |
Oops, something went wrong.