728x90
안녕하세요.
이번에는 UIKit에서 이미지를 비동기로 로딩할 수 있는 API들에 대해 소개해보려고 합니다.
보통 UICollectionView, UITableView에서 스크롤을 하면, 이미지 로딩 때문에 조금씩 끊기는 현상을 볼 수 있어요.
그 원인은
첫째, 이미지 로딩할 때 디코딩이 필요한데 디코딩 작업이 메모리를 많이 사용하기 때문이에요.
둘째, 이미지 디코딩은 main thread에서 작업을 해야 하고 화면에 출력될 때 디코딩하는 lazy 한 방식을 사용하기 때문이에요.
물론, background에서 로딩, 디코딩할 수 있는 API가 있지만 워낙 low-level의 API이고 메모리 관리를 직접 해줘야 하는 불편함이 있어서 쉬운 작업은 아니에요...ㅠㅠㅠ
그런데!! iOS 15부터 훨씬 쉽게 background에서 작업할 수 있는 API가 추가되었습니다.
한번 알아볼게요ㅎㅎ
## 1. UIKit
### 1.1 preparingForDisplay()
디코딩된 이미지를 반환하는 동기 API입니다.
그리고 background에서 동작이 가능합니다.
애플은 serial queue와 함께 사용하는 것을 권장하고 있어요.
// Create your serial queue for lining up the decoding tasks.
let serialQueue = ...
// In the view configuration method:
// Access the corresponding `UICollectionViewCell` / `UITableViewCell`.
let itemCell = ...
let image: UIImage = getImageForItem(item)
serialQueue.async {
// Call `preparingForDisplay`, which runs synchronously.
let decodedImage = image.preparingForDisplay()!
DispatchQueue.main.async {
// Fetch the relevant cell here instead of capturing it to ensure that the fetched cell belongs to the correct index path.
let itemCell = ...
// Set the decoded image as the image for the image view of the cell now that you have the decoded image.
itemCell.imageView.image = decodedImage
}
}
### 1.2 prepareForDisplay(completionHandler:)
디코딩된 이미지를 반환하는 비동기 API입니다.
// In the view configuration method:
// Access the corresponding `UICollectionViewCell` / `UITableViewCell`.
let itemCell = ...
let image: UIImage = getImageForItem(item)
image.prepareForDisplay { decodedImage in
// Fetch the relevant cell here instead of capturing it to ensure that the fetched cell belongs to the correct index path.
let itemCell = ...
// Set the decoded image as the image for the image view of the cell now that you have the decoded image.
itemCell?.imageView.image = decodedImage
}
### 1.3 byPreparingForDisplay()
async/await 패턴에서 사용할 수 있는 비동기 API입니다.
// In the view configuration method:
// Access the corresponding `UICollectionViewCell` / `UITableViewCell`.
let itemCell = ...
let image: UIImage = getImageForItem(item)
async {
// Start preparing the image the asynchronously.
let decodedImage = await image.byPreparingForDisplay()
// Set the decoded image to the cell.
itemCell.imageView.image = decodedImage
}
SwiftUI에서 비동기로 이미지를 로딩하고 싶을 땐 AsyncImage를 사용하면 됩니다!!ㅎㅎ
## 참고
- https://pspdfkit.com/blog/2021/ios-15-image-api/
이번 글은 여기서 마무리.
반응형
'UIKit' 카테고리의 다른 글
viewDidLayoutSubviews (0) | 2022.07.24 |
---|---|
UIKeyboardLayoutGuide (0) | 2022.03.29 |
DiffableDataSource를 사용해서 TableView 드래그&드롭 기능 넣기 (0) | 2022.02.19 |
DiffableDataSource (0) | 2022.02.19 |
UICollectionView (2) (0) | 2022.02.17 |