# ✏️ 13주차 \[8기\] B반 스터디 ## 🗓2023-04-08 **참여자** : 리지, vetto, 송준 **진행자** : vetto ## \[금주의 실험🔥\] Cache * 각 UI요소들의 역할은 아래와 같습니다. * ImageView(2개): 받아온 이미지를 표시합니다. * 이미지 받아오기(2개): URLSession을 통해 이미지 URL로부터 이미지를 받아와 ImageView에 표시합니다. 만약 캐시된 데이터가 있다면 캐시된 데이터를 활용합니다. * 캐시 데이터가 없을 경우: 이미지를 요청한 후, “새로운 이미지를 받아왔습니다" 출력 * 캐시 데이터가 있을 경우: 캐시된 데이터를 활용한 후, “캐시된 데이터가 있습니다.” 출력 * 이미지 초기화: ImageView의 image를 nil로 만들어줍니다. * 캐시 비우기: 저장된 캐시를 모두 제거합니다. * 각 UI요소들이 의도대로 동작하도록 Cache를 이용하여 구현합니다. * 디스크에 저장하는 시도는 하지 않아도 됩니다. ### NSCache ```swift struct NetworkManager { func loadImage(from imageURL: String, completion: @escaping ((Result<UIImage, NetworkError>) -> Void)) { guard let url = URL(string: imageURL) else { return } let urlRequest = URLRequest(url: url) let task = URLSession.shared.dataTask(with: urlRequest) { data, _, error in if error != nil { completion(.failure(.unknown)) return } if let data = data { guard let result = UIImage(data: data) else { completion(.failure(.decode)) return } completion(.success(result)) } } task.resume() } ``` ```swift //ViewController에서 확인하는 코드 private func fetchImage(from imageURL: String, imageView: UIImageView) { if let cachedImage = ImageCacheManager.shared.cachedImage(urlString: imageURL) { DispatchQueue.main.async { print("캐시된 데이터가 있습니다.") imageView.image = cachedImage } return } networkManager.loadImage(from: imageURL) { result in switch result { case .failure(let error): print(error.description) case .success(let image): ImageCacheManager.shared.setObject(image: image, urlString: imageURL) DispatchQueue.main.async { imageView.image = image print("새로운 이미지를 받아왔습니다.") } } } } ``` ### URLCache ```swift struct NetworkManager { func loadURLCachedImage(from imageURL: URLRequest, completion: @escaping ((Result<(Data), NetworkError>) -> Void)) { // MARK: task 생성 let task = URLSession.shared.dataTask(with: imageURL) { data, response, error in // MARK: task resume이 되면서 실행 if error != nil { completion(.failure(.unknown)) return } guard response is HTTPURLResponse else { completion(.failure(.response)) return } if let data = data, let response = response { let cachedResponse = CachedURLResponse(response: response, data: data) URLCache.shared.storeCachedResponse(cachedResponse, for: imageURL) print("새로 저장") completion(.success(data)) } } // MARK: task 생성 후 실행되는 코드 URLCache.shared.getCachedResponse(for: task) { cachedResponse in if let cachedResponse = cachedResponse { print("캐시된 데이터가 있습니다.") completion(.success(cachedResponse.data)) } else { task.resume() } } } } ``` ```swift // ViewController에서 실행하는 코드 private func downloadImage(from imageURL: String, imageView: UIImageView) { guard let url = URL(string: imageURL) else { return } let request = URLRequest(url: url) networkManager.loadURLCachedImage(from: request) { result in switch result { case .failure(let error): print(error.description) case .success(let data): DispatchQueue.main.async { let cachedImage = UIImage(data: data) imageView.image = cachedImage } return } } } ``` ###### tags: `toyo`