UIKIT
델리게이트 패턴으로 사진 선택하기
밤새는 탐험가89
2024. 12. 20. 15:06
1. 버튼 클릭 이벤트 연결 (imageSelectedButtonTapped)
- ImageUploadCell에서 imageSelectedButton의 클릭 이벤트가 델리게이트 패턴으로 연결됩니다.
private func imageSelectedButtonTapped() {
imageSelectedButton.addTarget(self,
action: #selector(didTappedSelectedButton),
for: .touchUpInside)
}
@objc private func didTappedSelectedButton() {
print("Button Tapped")
delegate?.didTappedSelectedButton(in: self) // 델리게이트를 통해 상위 클래스에게 이벤트 전달
}
- didTappedSelectedButton 메서드는 버튼 클릭 시 호출되며, 이를 델리게이트를 통해 상위 클래스(FeedViewController)에 전달합니다.
- 델리게이트는 ImageUploadCellDelegate 프로토콜을 준수하며, FeedViewController가 이를 구현합니다.
2. 델리게이트 메서드 처리 (FeedViewController)
- FeedViewController는 ImageUploadCellDelegate 프로토콜을 준수하며, 버튼 클릭 이벤트를 처리합니다.
extension FeedViewController: ImageUploadCellDelegate {
func didTappedSelectedButton(in cell: ImageUploadCell) {
var configuration = PHPickerConfiguration()
configuration.filter = .images
configuration.selectionLimit = 10
let picker = PHPickerViewController(configuration: configuration)
picker.delegate = self
present(picker, animated: true, completion: nil) // PHPicker를 표시
}
}
- didTappedSelectedButton 메서드에서 PHPickerViewController를 생성하여 이미지를 선택할 수 있는 뷰를 제공합니다.
3. 이미지 선택 및 저장 (PHPickerViewControllerDelegate)
- PHPickerViewControllerDelegate를 통해 선택된 이미지를 FeedViewController의 selectedImages 배열에 저장합니다.
func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
picker.dismiss(animated: true, completion: nil)
let group = DispatchGroup() // 비동기 작업 그룹 관리
for result in results {
if result.itemProvider.canLoadObject(ofClass: UIImage.self) {
group.enter()
result.itemProvider.loadObject(ofClass: UIImage.self) { object, error in
if let error = error {
print("Error loading image: \(error.localizedDescription)")
} else if let image = object as? UIImage {
DispatchQueue.main.async {
self.selelctedImages.append(image) // 이미지를 배열에 추가
}
}
group.leave()
}
}
}
group.notify(queue: .main) {
if let cell = self.collectionView.cellForItem(at: IndexPath(row: 0, section: 0)) as? ImageUploadCell {
print("Final selected images count: \(self.selelctedImages.count)")
self.photoAddCell(cell, didSelect: self.selelctedImages) // 델리게이트 메서드 호출
}
}
}
- 이미지는 비동기적으로 로드되며, 로드가 완료되면 selectedImages 배열에 저장됩니다.
- 모든 이미지 로드 작업이 완료되면 photoAddCell(_:didSelect:) 델리게이트 메서드를 호출합니다.
4. 셀에 이미지 전달 및 업데이트 (photoAddCell)
- photoAddCell 델리게이트 메서드는 ImageUploadCell의 updateImage 메서드를 호출하여 이미지를 전달하고 컬렉션뷰를 갱신합니다.
func photoAddCell(_ cell: ImageUploadCell, didSelect image: [UIImage]) {
print("Updating cell with images: \(image.count)")
cell.updateImage(image) // 셀에 선택한 이미지를 전달
}
5. 이미지 표시 (ImageUploadCell)
- ImageUploadCell의 updateImage 메서드는 전달받은 이미지를 selectedImages 배열에 저장하고, 컬렉션뷰를 리로드합니다.
func updateImage(_ images: [UIImage]) {
self.selectedImages = images // 선택된 이미지를 저장
}
var selectedImages: [UIImage] = [] {
didSet {
DispatchQueue.main.async {
print("Reloading data with images: \(self.selectedImages.count)")
self.selectedImageCollectionView.reloadData() // 컬렉션뷰 갱신
}
}
}
- selectedImages의 변경 감지(didSet)를 통해 컬렉션뷰를 갱신합니다.
- UICollectionViewDataSource의 메서드에서 selectedImages를 데이터소스로 사용하여 이미지를 표시합니다.
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return selectedImages.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: ImageCell.reuseIdentifier, for: indexPath) as? ImageCell else { return UICollectionViewCell() }
let image = selectedImages[indexPath.row]
cell.imageView.image = image // 이미지를 셀에 표시
return cell
}
델리게이트 패턴의 핵심 흐름 요약
- ImageUploadCell의 버튼 클릭 이벤트가 발생 → 델리게이트를 통해 FeedViewController에 전달.
- FeedViewController가 PHPicker를 표시 → 이미지를 선택하고 배열에 저장.
- 이미지를 ImageUploadCell에 전달 → updateImage로 selectedImages를 갱신.
- ImageUploadCell이 데이터를 기반으로 컬렉션뷰를 리로드 → 선택된 이미지를 화면에 표시.