-
AsyncImage 구현하기(2)SwiftUI 2023. 6. 9. 23:25
여기에서는 URLCache 를 이용해 CachedAsyncImage에 캐시기능을 추가하겠습니다. 우선 CachedAsyncImage에서만 사용하기 위해 해당 파일을 CachedAsyncImageViewModel에 fileprivate로 ImageCache 클래스를 구현합니다.
fileprivate final class ImageCache { static let shared = ImageCache() let cache: URLCache private init() { self.cache = URLCache(memoryCapacity: 32*1000*1000, diskCapacity: 100*1000*1000) } //캐시에 UIImage가 있는 경우 이미지를 반환하고 없는 경우 nil을 반환 func load(_ request: URLRequest) -> UIImage? { guard let response = cache.cachedResponse(for: request) else { return nil } guard let uiImage = UIImage(data: response.data) else { cache.removeCachedResponse(for: request) return nil } //print("cache hit: \(request.url!.absoluteString)") return uiImage } //캐시에 request에 해당 하는 response 값과 data를 이용해 CachedResponse를 생성해 저장 func store(_ request: URLRequest, response: URLResponse, data: Data) { cache.removeCachedResponse(for: request) let cachedResponse = CachedURLResponse(response: response, data: data) cache.storeCachedResponse(cachedResponse, for: request) } }
위의 캐시를 이용해 이미지를 패치 시 우선 load 함수를 호출해 해당 request 에 대한 이미지가 있는 지 확인 후 있으면 해당 이미지를 사용해 Image 뷰를 생성하고 현재 CachedAsynImagePhase 상태를 success 로 변경합니다. request 대한 값이 없는 경우 이전과 동일하게 request를 요청하고 성공적으로 수행하면 ImageCache에 store 함수를 호출해 request에 대한 CachedResponse를 저장합니다.
func fetch(url: URL?) async { ... let request = URLRequest(url: url) if let uiImage = ImageCache.shared.load(request) { phase = .success(Image(uiImage: uiImage)) } let configuration = URLSessionConfiguration.default configuration.urlCache = ImageCache.shared.cache configuration.httpMaximumConnectionsPerHost = 10 let session = URLSession(configuration: configuration) do { let (data, response) = try await session.data(for: request) let httpResponse = response as! HTTPURLResponse if httpResponse.statusCode < 200 || httpResponse.statusCode > 300 { phase = .failure(CachedAsyncImageError.httpResponseError(httpResponse.statusCode)) return } guard let uiImage = UIImage(data: data) else { phase = .failure(CachedAsyncImageError.imageCreatedFail) return } phase = .success(Image(uiImage: uiImage)) ImageCache.shared.store(request, response: response, data: data) } catch { phase = .failure(error) }
위에서 보는 바와 같이 캐시 설정을 위해 URLSession.shared를 사용하는 대신 새로운 URLSession을 생성하고 이 세션을 사용하여 요청을 보내게 됩니다.
해당 소스는 https://github.com/hjpark0724/CacheAsyncImage 에서 확인할 수 있습니다.
'SwiftUI' 카테고리의 다른 글
PhotoPicker를 구현해 ProfileImage 뷰 구현하기 (0) 2023.06.10 LibraryContentProvider 로 XCode 라이브러리에 뷰 추가하기 (0) 2023.06.10 AsyncImage 구현하기(1) (0) 2023.06.09 Core Buletooth 사용하기 (0) 2023.06.06 SwiftUI ScrollView 와 ForEach 로 구현한 영화 포스트 리스트 (0) 2020.08.25