카테고리 없음

사진 갤러리에 접근하기 2 (부제 PHPicker)

papayetoo 2022. 1. 18. 22:24

iOS 14.0 부터 가능한 PHPicker가 등장했다. 음...아직 사진을 활용하는 게시판이나 어플을 만들어 본적이 없어 PHPicker는 더욱이나 생소하다. 한 번 알아보자

 

PHPicker

PHPicker를 사용하려면 우선 iOS 14.0 버젼 이상이여야 한다. 그리고 import PhotosUI 를 해줘야 한다. Photos에 있지 않고 PhotosUI에 있다. UIImagePickerController와 많은 점이 유사한데, 다른 점이 있다면 사진 선택 개수에 제한이 없고 또 사진 종류에 대한 필터를 걸 수 있다. 굉장히 유용한 친구입니다.

일단 PHPicker를 볼 수 있는 화면을 구성해봅시다. 이전 2022.01.18 - [Swift] - 사진 갤러리 이미지에 접근하기 1 (부제 UIImagePickerController) 에 마지막 화면에서 버튼 위치를 옮기고 다른 버튼을 하나 더 추가해봅시다.

 

오른쪽 화면이 PHPicker를 보여줄 버튼

import UIKit
import PhotosUI

class ViewController: UIViewController {

    @IBOutlet weak var imagePickerButton: UIButton!
    @IBOutlet weak var phPickerButton: UIButton!
    @IBOutlet weak var selectedImageView: UIImageView!
    var selectedImage: UIImage? = nil {
        didSet {
            self.selectedImageView.image = selectedImage
        }
    }
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }
    
    @IBAction
    private func didTouchImagePickerButton(_ sender: UIButton) {
        guard UIImagePickerController.isSourceTypeAvailable(.photoLibrary) else {
            return
        }
        let imagePickerController = UIImagePickerController()
        imagePickerController.delegate = self
        self.present(imagePickerController, animated: true)
    }
    
//  1.
    @IBAction
    private func didTouchPHPickerButton(_ sender: UIButton) {
        if #available(iOS 14.0, *) {
            var phPickerConfiguration = PHPickerConfiguration()
            phPickerConfiguration.selectionLimit = 1
            let phPickerContoller = PHPickerViewController(configuration: phPickerConfiguration)
            phPickerContoller.delegate = self
            self.present(phPickerContoller, animated: true)
        } else {
            let alertViewController = UIAlertController(title: "PHPicker 사용불가", message: "iOS 14.0 이하 버젼에서 사용 불가", preferredStyle: .alert)
            self.present(alertViewController, animated: true)
        }
            
    }
}

extension ViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
        guard let originalImage = info[.originalImage] as? UIImage else {
            return
        }
        self.selectedImage = originalImage
        picker.dismiss(animated: true, completion: nil)
    }
    
    func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
        picker.dismiss(animated: true, completion: nil)
    }
}

extension ViewController: PHPickerViewControllerDelegate {
//  2 PHPickerViewControllerDelegate에서 사진을 불러오는 곳
    @available(iOS 14.0, *)
    func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
//  3
        guard let itemProvider = results.first?.itemProvider,
              itemProvider.canLoadObject(ofClass: UIImage.self) else {
            return
        }
        itemProvider.loadObject(ofClass: UIImage.self) {[weak self] (image, error) in
            self?.selectedImage = image as? UIImage
        }
        picker.dismiss(animated: true, completion: nil)
    }
}

이전 코드에서 다른 점을 살펴볼까요?

  1. 오른쪽 버튼을 눌렀을 때 실행하는 함수입니다. 앞에서도 말했듯이 PHPicker가 iOS 14.0 이후 부터 사용할 수 있기 때문에 #available로 구분해 줬습니다.
  2. PHPickerControllerDelegate를 구현해줬는데 여기서도 마찬가지로 @available(iOS 14.0, *)으로 구분했습니다. 그리고 UIImagePickerController를 사용했을 때 보다 어려운 점은 이미지를 불러오기가 좀 어려운데요..
  3. 이미지 가져오기 어려움
    1. 예제에서는 하나의 이미지만 선택할 수 있도록 제한상태라 선택한 이미지의 첫 번째만을 가져와서 그 itemProvider를 가져옵니다. 그리고 itemProvider에서 UIImage 타입으로 변환이 가능하지 알아봐요 불가능하다면 else 문을 타고 종료될 거에요. * 여기에서 itemProvider는 선택한 이미지 asset의 representation이라고 합니다. *
    2. UIImage 타입으로 변환이 가능한 상태라면 loadObject(ofClass:completion)을 통해 이미지를 가져올 수 있어요. completion은 escaping 클로져로 NSItemProviderReading? 과 Error?를 매개변수로 받고 Void를 리턴합니다. 클로져 내부에서 읽은 결과인 NSItemProviderReading을 UIImage로 변경하고 내부 property인 selectedImage에 대입합니다.