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
}

 

 

델리게이트 패턴의 핵심 흐름 요약

  1. ImageUploadCell의 버튼 클릭 이벤트가 발생 → 델리게이트를 통해 FeedViewController에 전달.
  2. FeedViewController가 PHPicker를 표시 → 이미지를 선택하고 배열에 저장.
  3. 이미지를 ImageUploadCell에 전달 → updateImage로 selectedImages를 갱신.
  4. ImageUploadCell이 데이터를 기반으로 컬렉션뷰를 리로드 → 선택된 이미지를 화면에 표시.