import Foundation import UIKit class DownloadService { static let shared = DownloadService() private let cache = NSCache() private var activeTasks: [URL: URLSessionDataTask] = [:] private init() { cache.totalCostLimit = 50 * 1024 * 1024 // 50 MB cache limit } func downloadGIF(from urlString: String, completion: @escaping (Data?, Error?) -> Void) { guard let url = URL(string: urlString) else { completion(nil, NSError(domain: "DownloadService", code: 1, userInfo: [NSLocalizedDescriptionKey: "Invalid URL"])) return } // Check if the GIF is already cached let cacheKey = url.absoluteString as NSString if let cachedData = cache.object(forKey: cacheKey) { completion(cachedData as Data, nil) return } // Cancel any existing tasks for this URL activeTasks[url]?.cancel() // Create a new download task let task = URLSession.shared.dataTask(with: url) { [weak self] data, response, error in defer { self?.activeTasks.removeValue(forKey: url) } guard let self = self, error == nil, let data = data else { DispatchQueue.main.async { completion(nil, error ?? NSError(domain: "DownloadService", code: 2, userInfo: [NSLocalizedDescriptionKey: "Failed to download GIF"])) } return } // Cache the downloaded data self.cache.setObject(data as NSData, forKey: cacheKey, cost: data.count) DispatchQueue.main.async { completion(data, nil) } } // Store and start the task activeTasks[url] = task task.resume() } func cancelAllTasks() { activeTasks.values.forEach { $0.cancel() } activeTasks.removeAll() } }