카테고리 없음
사진 갤러리에 접근하기 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) 에 마지막 화면에서 버튼 위치를 옮기고 다른 버튼을 하나 더 추가해봅시다.
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)
}
}
이전 코드에서 다른 점을 살펴볼까요?
- 오른쪽 버튼을 눌렀을 때 실행하는 함수입니다. 앞에서도 말했듯이 PHPicker가 iOS 14.0 이후 부터 사용할 수 있기 때문에 #available로 구분해 줬습니다.
- PHPickerControllerDelegate를 구현해줬는데 여기서도 마찬가지로 @available(iOS 14.0, *)으로 구분했습니다. 그리고 UIImagePickerController를 사용했을 때 보다 어려운 점은 이미지를 불러오기가 좀 어려운데요..
- 이미지 가져오기 어려움
- 예제에서는 하나의 이미지만 선택할 수 있도록 제한상태라 선택한 이미지의 첫 번째만을 가져와서 그 itemProvider를 가져옵니다. 그리고 itemProvider에서 UIImage 타입으로 변환이 가능하지 알아봐요 불가능하다면 else 문을 타고 종료될 거에요. * 여기에서 itemProvider는 선택한 이미지 asset의 representation이라고 합니다. *
- UIImage 타입으로 변환이 가능한 상태라면 loadObject(ofClass:completion)을 통해 이미지를 가져올 수 있어요. completion은 escaping 클로져로 NSItemProviderReading? 과 Error?를 매개변수로 받고 Void를 리턴합니다. 클로져 내부에서 읽은 결과인 NSItemProviderReading을 UIImage로 변경하고 내부 property인 selectedImage에 대입합니다.