서버 통신 한 이미지 파일 저장하고 불러오기
서버 통신을 통해 받은 이미지 url을 데이터 베이스에 저장한 후 꺼내와서 이미지를 로드하면 오류가 발생한다.
데이터 베이스 내부에서 꺼내온 값을 글로벌로 접근하려고 하기 때문에 발생한 오류이다.
DispatchQueue 외부에서 상수로 저장한 후 사용하면 오류가 나지 않는다.
이미지를 하나하나 불러올 때 마다 네트워크 통신을 하게 되는데, 이미지의 용량이 크거나 로드할 데이터가 많다면 이미지 로드가 오래 걸릴 수 있다.
❓ 어떻게 해결해야 할까?
이미지 구현을 셀 구성할 때 하지말고, 미리 UIImage 형식으로 변환 후 셀에 보여주는 것.
하지만 이 또한 데이터가 여러개라면 변환하는 데에 오랜 시간이 걸리고,
사용자가 보지 않고 넘겨버릴 이미지까지 모두 로드를 해야하기 때문에 비효율적이다.
prepareForReuse() 사용하기 → 재사용 시 nil로 초기화
이미 로드한 이미지도 지나갔다가 돌아가면 또 다시 불러와야 하는 문제가 있다.
➡️ 이미지 url을 저장하는 것 보다는 이미지 자체를 저장하여 사용하는 것이 좋다.
- jpg 파일을 document에 저장하기
- Data타입으로 변환하여 default.realm의 column으로 저장하기
💡 이미지 파일을 document에 저장하기
넷플릭스 오프라인 저장과 같은 기능이다.
- 컬럼 만들어서 이미지 파일 저장하기 → 가장 직관적
- pk 이용하여 이미지 파일 명 지정하여 저장
- 도큐먼트 경로 찾기
guard let documentDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else { return }
document 폴더까지의 경로를 찾기
- 저장할 경로 설정(세부 경로, 이미지를 저장할 위치)
let fileURL = documentDirectory.appendingPathComponent(fileName)
총 url을 찾아준다.
appendingPathComponent → ‘ / ‘ 슬래시 역할
- 이미지 변환
guard let data = image.jpegData(compressionQuality: 0.5) else { return }
compressionQuality로 압축 가능
- 이미지 저장
이미지 저장 시 사용자 기기 저장공간을 체크한 후 저장해야 한다.
백업복구,,
do {
try data.write(to: fileURL)
} catch let error {
print("file save error", error)
// 사용자에게 보여줄 액션을 구현해야 한다.
}
💻 전체 코드
import UIKit
extension UIViewController {
//document 폴더에 이미지를 저장하는 메서드
func saveImageToDocument(fileName: String, image: UIImage) {
// 1. 도큐먼트 경로 찾기
guard let documentDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else { return }
// 2. 저장할 경로 설정(세부 경로, 이미지를 저장할 위치)
let fileURL = documentDirectory.appendingPathComponent(fileName)
// 3. 이미지 변환
guard let data = image.jpegData(compressionQuality: 0.5) else { return }
// 4. 이미지 저장
do {
try data.write(to: fileURL)
} catch let error {
print("file save error", error)
// 사용자에게 보여줄 액션을 구현해야 한다.
}
}
}
document파일에 이미지 파일이 저장된다.
사진을 여러장 저장할 때 파일명 설정이나 순서 등 문제 발생 요소가 많다.
💡 저장된 이미지 불러오기
- 도큐먼트 경로 찾기
guard let documentDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else { return UIImage(systemName: "photo")! }
- 경로 설정(세부 경로, 이미지가 저장되어 있는 위치)
let fileURL = documentDirectory.appendingPathComponent(fileName)
- 해당 파일에 해당 파일 이름이 존재하는지 판단 후 UIImage return
if FileManager.default.fileExists(atPath: fileURL.path) {
return UIImage(contentsOfFile: fileURL.path)!
} else {
return UIImage(systemName: "photo")!
}
viewcontroller에서는 이미지 관련 통신 없이 이미지를 보여줄 수 있다.
해상도 때문에 작게 보여주거나 이미지를 크게 보여줘야 하는 경우 파일 용량을 나눠 두 개의 파일을 저장하기도 한다.
이미지 폴더 만들어서 백업 복구할 때 폴더 자체로 할 수 있다.
보안이 중요한 데이터를 다뤄야 한다면
→ realm 폴더에 암호화 가능
→ library 폴더 내에 저장하는 것도 좋음(접근이 어렵기 때문)
library폴더에 저장하려면 let realm = try! Realm()
구문으로 접근할 수 없다.
💡 이미지 파일 삭제하기
❗️ 주의
\
realm에 데이터가 삭제되면 data 상수 값까지 삭제가 되어 이미지 파일을 삭제하려고 할 때 접근을 하지 못한다.
⇒ 코드의 순서가 바뀌어야 한다.
레코드를 날리기 전에 이미지 파일 삭제 후 레코드 삭제해야 한다.
'iOS > 🔎 swift 정리하기' 카테고리의 다른 글
[iOS/Swift] MapKit - 원하는 곳에 어노테이션을 찍어보자 (0) | 2023.10.01 |
---|---|
[iOS/Swift] Realm - 백업 및 복구 구현하기 (0) | 2023.09.16 |
[iOS/Swift] Realm - Migration (0) | 2023.09.16 |
[iOS/Swift] Realm - CRUD (0) | 2023.09.16 |
[iOS/Swift] - Swift에서 값을 전달하는 방법 (0) | 2023.09.03 |