Skip to content

Commit

Permalink
Replace legacy image downloader with new actor-based implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
azarovalex committed Jan 23, 2024
1 parent ce064ed commit f3f3edc
Show file tree
Hide file tree
Showing 16 changed files with 163 additions and 532 deletions.
192 changes: 0 additions & 192 deletions Sources/MapboxNavigation/ImageDownload.swift

This file was deleted.

119 changes: 0 additions & 119 deletions Sources/MapboxNavigation/ImageDownloader.swift

This file was deleted.

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)
}
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()
}
}
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
}
}
Loading

0 comments on commit f3f3edc

Please sign in to comment.