카테고리 없음

PHPickerController

ghnn 2025. 8. 8. 13:29

이전에 앨범을 연동할 때 UIImagePickerController를 사용했었는데

UIImagePickerController의 sourceType 중 앨범 연동 기능이 18.5 이후 Deprecated 된다는 소식을 접했다.

애플에서는 PHPickerController의 사용을 추천한다고 한다.

 

추가된 기능으로는 이미지 여러 장을 한 번에 선택할 수 있는 기능,

사용자가 허락한 미디어만 사용가능(보안 개선) 및 이미지를 안정적으로 처리한다고 합니다.


사용법

import PhotosUI

import PhotosUI

 

PHPickerConfiguration을 생성해 설정.

var configuration = PHPickerConfiguration()
configuration.selectionLimit = 5
configuration.filter = .images
  • selectionLimit: 선택할 수 있는 최대 값을 정해준다. 기본 값은 1이며, 제한이 없다면 0을 입력
  • filter: 표시하는 타입을 제한한다. 기본 값은 nil이며, nil일 경우 모든 타입을 표시한다.

filter에 들어갈 수 있는 값은 아래 링크에 있다.

https://developer.apple.com/documentation/photosui/phpickerfilter-swift.struct

 

PHPickerFilter | Apple Developer Documentation

A type that defines the filter to apply to the photo library.

developer.apple.com

 

원래 images, LivePhotos, videos만 있는 줄 알고

.any(of: [.images, .livePhotos]) 만 해두고 실행해봤는데 전부 나오길래 별 생각 없었는데

찾아보니 iOS 15부터 screenshots 등 꽤 많은 타입들이 추가됐다.

 

그럼에도 스크린샷을 포함한 모든 이미지가 나오길래 뭐지 싶어서 찾아봤는데

대부분 초기에 나왔던 images, livePhotos, videos만 다루고 이후 정보가 별로 없어서 지피티에게 물어봤다.

 

 

뭐 그렇다고 하는데 그러면 screenshots을 제외하고 싶다면

configuration.filter = .any(of: [.images, .not(.screenshots)]) 
// 인 줄 알았지만 .any는 "or(||)" 연산자라서 원하는 결과가 나오지 않는다고 한다

// "and(&&)" 연산자인 .all을 사용하면 된다!
configuration.filter = .all(of: [.images, .not(.screenshots)])

 

screentshots만 보여주고 싶다면

configuration.filter = .screenshots

이런 방식으로 사용하면 된다.

 

PHPickerController 생성

let imagePicker = PHPickerViewController(configuration: configuration)
imagePicker.delegate = self

self.present(imagePicker, animated: true)

 

Delegate 채택

채택한 뒤 required method인 아래 메서드를 정의해줘야 한다.

extension AddNewContentViewController: PHPickerViewControllerDelegate {
    func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
        
    }
}

 

이미지 저장

func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
    // 우선 피커 디스미스
    picker.dismiss(animated: true)
    
    // 결과로 나온 값이 배열이기 때문에 forEach로 전부 돌려준다.
    // 한 장만 가져오도록 설정했다면 results.first?.itemProvider로 접근하면 된다.
    results.forEach { result in
        
        // itemProvider에서 UIImage로 로드 가능한지 조건문으로 체크
        if result.itemProvider.canLoadObject(ofClass: UIImage.self) {
            
            // 로드 핸들러를 통해 UIImage를 처리한다.
            result.itemProvider.loadObject(ofClass: UIImage.self) { [weak self] item, error in
                
                // 현재 item은 (any NSItemProviderReading)? 타입이기 때문에 타입캐스팅이 필요하다.
                guard let self, let image = item as? UIImage else { return }
                
                // 이후 필요한 곳에 넣어주면 된다.
                self.images.append(image)
            }
        }
    }
}

 

필자는 배열에 넣어줄 것이기 때문에 그대로 처리했지만

이미지를 한 장만 가져와 바로 UI에 적용할 것이라면 꼭 메인스레드를 명시해주고 사용해야 한다.

loadObject가 비동기로 처리되기 때문이라고 한다.


참고한 자료

 

iOS 14+ ) PHPicker

안녕하세요 :) Zedd입니다, WWDC를 보다가 정말정말..새로운것을 보게되어서 이렇게 공부하게 되었어요 :D 너무 재밌당 developer.apple.com/videos/play/wwdc2020/10652/ Meet the new Photos picker - WWDC 2020 - Videos - Appl

zeddios.tistory.com

 

[Swift/TIL #9] PHPickerViewController에 대하여

[TIL #9] 2023 / 04 / 03 ~ 2023 / 04 / 06 사진을 가져오려 하는데 iOS 14 이상부터는 UIImagePickerController 대신 PHPickerViewController를 사용하라고 하더라고요. 그래서 오늘은 PHPickerViewController에 대해서 알아보겠

ios-daniel-yang.tistory.com