# ✏️ 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`