사진 클릭시 캘린더 사진 지정하기

pengsang·2023년 8월 21일

개발일지

목록 보기
4/5
post-thumbnail

PHPickerViewController

https://developer.apple.com/documentation/photokit/phpickerviewcontroller

정의

사진첩으로부터 사진들을 선택할 수 있도록 유저 인터페이스를 제공하는 뷰 컨트롤러


예시

아래 화면과 같이 이미지 클릭시 사진첩을 열어 사진을 선택할 수 있도록 한다


구현

구현된 프로젝트 링크 ->
https://github.com/sang9984/PHPickerViewController-test

1. import PhotosUI

PHPickerViewController를 사용하기 위해서는 PhotosUI를 import 해야 한다

import PhotosUI

2. 제스쳐 설정하기

UITapGestureRecognizer는 제스쳐를 인식할 수 있도록 도와주는 도구다
해당 객체를 가져와 대상을 지정하고 화면 내에 존재하는 객체(image 등)에 대한 제스쳐 인식을 활성화 해야 한다

func setupTapGesture() {
        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(touchUpImageView))
        image.isUserInteractionEnabled = true
        image.addGestureRecognizer(tapGesture)
    }

또한 #selector()를 통해 제스쳐를 인식할 경우 수행할 기능에 대해 함수로 정의해야 한다
제스쳐가 인식되면 아래 @objc 함수를 실행시켜 함수 내 기능을 수행한다
setupImagePicker()에 대해서는 3번에서 설명

@objc func touchUpImageView() {
        setupImagePicker()
    }

3. pickerView 설정하기

여기서 필요한 객체가 2가지가 있다

  • PHPickerConfiguration() -> PHPickerViewController의 동작 등을 구성하는데 사용되는 객체
  • PHPickerViewController() -> 피커뷰 컨트롤러를 실행시키기 위한 객체
func setupImagePicker() {
        // PHPickerConfiguration() -> PHPickerViewController의 동작 등을 구성하는데 사용되는 객체
        // 해당 객체를 통해 선택되는 사진의 개수나 파일 종류를 지정할 수 있다
        var configuration = PHPickerConfiguration()
        // 사진 선택 개수 제한: 0이면 제한없음, 0이외의 수 -> 해당 개수만큼 제한
        configuration.selectionLimit = 0
        // 선택할 수 있는 파일의 종류
        configuration.filter = .any(of: [.images, .videos])

        // 기본설정을 바탕으로, 피커뷰컨트롤러 생성
        let picker = PHPickerViewController(configuration: configuration)
        // 피커뷰 컨트롤러의 대리자 설정
        picker.delegate = self
        // 피커뷰 띄우기
        self.present(picker, animated: true, completion: nil)
    }

4. Delegate 설정하기

피커뷰에 대한 기본적인 설정이 완료된 경우 delegate를 통해 실질적인 기능을 수행할 수 있도록 해야 한다

extension ViewController: PHPickerViewControllerDelegate {
    
    // 사진이 선택이 된 후에 호출되는 메서드
    func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
        // 피커뷰 dismiss
        picker.dismiss(animated: true)
        
        let itemProvider = results.first?.itemProvider
        
        if let itemProvider = itemProvider, itemProvider.canLoadObject(ofClass: UIImage.self) {
            itemProvider.loadObject(ofClass: UIImage.self) { (image, error) in
                DispatchQueue.main.async {
                    // 이미지뷰에 표시
                    self.image.image = image as? UIImage
                }
            }
        } else {
            print("이미지 불러오기 실패")
        }
    }
}

전체 예시 코드

import UIKit
import PhotosUI

class ViewController: UIViewController {
    
    // 이미지 생성
    let image: UIImageView = {
        let image = UIImageView()
        image.image = UIImage(named: "swift-og")
        image.layer.cornerRadius = 100
        image.clipsToBounds = true
        
        return image
    }()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        setupTapGesture()
        setupAutolayout()
    }
    
    func setupAutolayout() {
        image.translatesAutoresizingMaskIntoConstraints = false
        
        view.addSubview(image)
        
        NSLayoutConstraint.activate([
        
            image.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            image.centerYAnchor.constraint(equalTo: view.centerYAnchor),
            image.heightAnchor.constraint(equalToConstant: 200),
            image.widthAnchor.constraint(equalToConstant: 200)
        ])
    }
    
    //MARK: - pickerViewController 기본 설정

    func setupTapGesture() {
        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(touchUpImageView))
        image.isUserInteractionEnabled = true
        image.addGestureRecognizer(tapGesture)
    }
    
    // 제스쳐에서 addTarget을 통해 지정한 함수
    // 제스쳐 발생시 어떤 기능을 수행해야 하는지 정의하는 함수
    @objc func touchUpImageView() {
        setupImagePicker()
    }

    func setupImagePicker() {
        // PHPickerConfiguration() -> PHPickerViewController의 동작 등을 구성하는데 사용되는 객체
        // 해당 객체를 통해 선택되는 사진의 개수나 파일 종류를 지정할 수 있다
        var configuration = PHPickerConfiguration()
        // 사진 선택 개수 제한: 0이면 제한없음, 0이외의 수 -> 해당 개수만큼 제한
        configuration.selectionLimit = 0
        // 선택할 수 있는 파일의 종류
        configuration.filter = .any(of: [.images, .videos])

        // 기본설정을 바탕으로, 피커뷰컨트롤러 생성
        let picker = PHPickerViewController(configuration: configuration)
        // 피커뷰 컨트롤러의 대리자 설정
        picker.delegate = self
        // 피커뷰 띄우기
        self.present(picker, animated: true, completion: nil)
    }
    
}
//MARK: - 피커뷰 델리게이트 설정

extension ViewController: PHPickerViewControllerDelegate {
    
    // 사진이 선택이 된 후에 호출되는 메서드
    func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
        // 피커뷰 dismiss
        picker.dismiss(animated: true)
        
        let itemProvider = results.first?.itemProvider
        
        if let itemProvider = itemProvider, itemProvider.canLoadObject(ofClass: UIImage.self) {
            itemProvider.loadObject(ofClass: UIImage.self) { (image, error) in
                DispatchQueue.main.async {
                    // 이미지뷰에 표시
                    self.image.image = image as? UIImage
                }
            }
        } else {
            print("이미지 불러오기 실패")
        }
    }
}
profile
내 꿈은 고등어

0개의 댓글