Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
Tags
- 리펙터링
- collectionview
- 리팩토링
- clean architecture
- 클린 코드
- Refactoring
- Clean Code
- UITextView
- Human interface guide
- 리펙토링
- UICollectionView
- rxswift
- tableView
- map
- SWIFT
- MVVM
- uiscrollview
- Observable
- HIG
- Xcode
- ribs
- swiftUI
- 스위프트
- swift documentation
- ios
- combine
- Protocol
- uitableview
- 애니메이션
- RxCocoa
Archives
- Today
- Total
김종권의 iOS 앱 개발 알아가기
[iOS - swift] 여러개의 이미지 prefetch, 이미지 다운로드 방법 (#SDWebImage, DispatchGroup, RxSwift) 본문
iOS 응용 (swift)
[iOS - swift] 여러개의 이미지 prefetch, 이미지 다운로드 방법 (#SDWebImage, DispatchGroup, RxSwift)
jake-kim 2024. 4. 10. 01:17이미지 prefetch, 이미지 다운로드
- SDWebImage를 사용하여 쉽게 prefetch, 이미지 다운로드가 가능
- prefetch를 해놓으면 이미지를 memory, disk 캐싱해놓는데 큰 이미지나 즉각적으로 화면에 보여져야하는 이미지들은 prefetch해놓는것이 중요
- SDWebImage의 캐싱 구현 코드 분석은 이전 포스팅 글 참고
이미지 prefetch
- 이미지를 관리할 때는 보통 로컬이 아닌 서버로부터 url을 받아서 이 url로 이미지를 띄워주는데, 이 때 url을 가지고 이미지를 바로 여러장을 띄워주려고 할때 시간이 오래 걸리는 문제가 존재
- prefetch를 사용하면 SDWebImage에서 memory, disk 캐싱하여 효율적으로 이미지 표출이 가능
- ImageManager라는 이름으로 prefetch 접근할 수 있도록 선언하고 SDWebImagePrefetcher를 통해 손쉽게 prefetch 기능 사용
import SDWebImage
enum ImageManager {
private static let Prefetcher = SDWebImagePrefetcher.shared
static func prefetch(urls: [URL], completion: @escaping () -> Void) {
Prefetcher.prefetchURLs(urls, progress: nil) { successedCount, skippedCount in
completion()
}
}
}
이미지 다운로드
- 이미지 다운 역시도 SDWebImageDownloader.shared로 손쉽게 사용이 가능
static func downloadData(url: URL, completion: @escaping (Data) -> Void) {
Downloader.downloadImage(with: url, options: [], progress: nil) { (image, data, error, finished) in
if let data = data, finished {
completion(data)
} else if let error = error {
print("이미지 다운로드 실패 URL \(url): \(error.localizedDescription)")
}
}
}
이미지 여러개 다운로드 (DispatchGroup으로 구현 방법)
- 여러개의 URL을 전달하고 모든 URL의 이미지를 다운 받았을 때 콜백을 받고싶은 경우?
- DispatchGroup 사용
- 자세한 개념은 이전 포스팅 글 참고: async 처리를 순서대로 하고싶은 경우? DispatchGroup 사용
- DispatchGroup 인스턴스를 하나 만들고 async작업이 다 끝난 후에 notify(queue:) 함수로 모든 async작업이 끝난 타이밍에 completion을 넘겨줌
static func downloadDatas(urls: [URL], completion: @escaping ([Data]) -> Void) {
let group = DispatchGroup()
var imagesData = [Data]()
urls.forEach { url in
// TODO...
}
group.notify(queue: .main) {
print("다운 완료:", imagesData.count)
completion(imagesData)
}
}
- url.forEach를 돌면서 async작업이 시작하기 전에 enter()하여 기다리는 개수를 설정하고 async작업이 끝나는 시점에는 leave()로 기다리는 개수를 제거하여 0이 되면 위에서 작성한 notify가 실행되도록 구현
urls.forEach { url in
// 1
print("enter")
group.enter()
downloadData(url: url, completion: { data in
imagesData.append(data)
// 2
print("leave")
group.leave()
})
}
- 사용하는 쪽)
let urls = [
"https://cdn.pixabay.com/photo/2016/02/21/06/22/macbook-air-1213180_1280.jpg",
"https://cdn.pixabay.com/photo/2019/02/04/06/46/apple-3974057_1280.jpg",
"https://cdn.pixabay.com/photo/2018/07/09/18/17/apple-3526737_1280.jpg",
"https://images.pexels.com/photos/4246192/pexels-photo-4246192.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2"
].compactMap(URL.init(string:))
ImageManager.downloadDatas(urls: urls) { datas in
print("res:", datas)
}
/*
enter
enter
enter
enter
leave
leave
leave
leave
다운 완료: 4
*/
이미지 여러개 다운로드 (RxSwift로 구현방법)
- RxSwift로하면 조금 더 간략하게 표현이 가능
- 마찬가지로 ImageManagerRx라는 타입을 만들고 Single을 반환하여 성공/실패 결과로 받도록 단일 Data를 받는 함수 구현
enum ImageManagerRx {
private static let Downloader = SDWebImageDownloader.shared
static func downloadData(url: URL) -> Single<Data> {
.create { observer in
Downloader.downloadImage(with: url) { image, data, error, finished in
if let error {
observer(.failure(error))
} else if let data {
observer(.success(data))
} else {
observer(.failure(NSError()))
}
}
return Disposables.create()
}
}
}
- 여러개의 데이터를 다 받을때까지 기다려야 하므로 위 함수를 zip으로 묶으면 완성
static func downloadDatas(urls: [URL]) -> Single<[Data]> {
let observables = urls.map { downloadData(url: $0) }
return Single.zip(observables)
}
* 전체 코드: https://github.com/JK0369/ExPrefetch
* 참고
'iOS 응용 (swift)' 카테고리의 다른 글
Comments