diff --git a/EmployeeDirectory/Services/ImageCacheService.swift b/EmployeeDirectory/Services/ImageCacheService.swift new file mode 100644 index 0000000..b28b3c3 --- /dev/null +++ b/EmployeeDirectory/Services/ImageCacheService.swift @@ -0,0 +1,58 @@ +// +// ImageCacheService.swift +// EmployeeDirectory +// +// Created by Matt Bruce on 1/20/25. +// + +import Foundation +import UIKit + +public class ImageCacheService { + public static let shared = ImageCacheService() // Default shared instance + + private let memoryCache = NSCache() + private let fileManager = FileManager.default + private let cacheDirectory: URL = { + FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask)[0] + }() + + public init() {} + + public func loadImage(from url: URL) async -> UIImage? { + let uniqueKey = String(url.absoluteString.hashValue) + let cacheKey = uniqueKey as NSString + + if let cachedImage = memoryCache.object(forKey: cacheKey) { + return cachedImage + } + + let diskImagePath = cacheDirectory.appendingPathComponent(uniqueKey) + if let diskImage = UIImage(contentsOfFile: diskImagePath.path) { + memoryCache.setObject(diskImage, forKey: cacheKey) + return diskImage + } + + if let networkImage = await fetchFromNetwork(url: url) { + memoryCache.setObject(networkImage, forKey: cacheKey) + try? saveImageToDisk(image: networkImage, at: diskImagePath) + return networkImage + } + + return nil + } + + private func fetchFromNetwork(url: URL) async -> UIImage? { + do { + let (data, _) = try await URLSession.shared.data(from: url) + return UIImage(data: data) + } catch { + return nil + } + } + + private func saveImageToDisk(image: UIImage, at path: URL) throws { + guard let data = image.pngData() else { return } + try data.write(to: path) + } +}