πͺ iOS 14+ PHPickerViewController μ¬μ£Όμ¬μ£Όμ¬
κΈ°μ‘΄μ μ§μνλ UIPickerViewController κ° μμλλ°μ! iOS 14 μμ μλ‘μ΄ Photo Picker κ° λμμ΄λ€!
μμ κ°λ°μ λ¬Έμλ₯Ό μ΄ν΄λ³΄μꡬμ!
PHPickerViewController
ν΄λμ€λ UIImagePickerController
μ λμμ
λλ€. PHPickerViewController
λ μμ μ±κ³Ό μ λ’°μ±μ κ°μ νκ³ λ€μκ³Ό κ°μ κ°λ°μμ μ¬μ©μμκ² μ΄μ μ μ 곡ν©λλ€.
- Deferred image loading and recovery UI
μ§μ°λ μ΄λ―Έμ§ λ‘λ©κ³Ό 볡ꡬ UI
- Reliable handling of large and complex assets, like RAW and panoramic images
RAW λ° νλ ΈλΌλ§ μ΄λ―Έμ§μ κ°μ ν¬κ³ 볡μ‘ν μμ μ μμ μ μΈ μ²
(RAW λ μ΄λ―Έμ§ νμΌ ν¬λ§·μ΄λ€. λ€λ₯Έ νμ₯μλ€λ³΄λ€ ν¬κΈ°κ° λ§€μ° ν¬μ§λ§ μ¬μ§νΈμ§μ μ μ©νλ€κ³ νλ€. iPhone 12 νλ‘ λ° νλ‘λ§₯μ€μμλΆν° 촬μκ°λ₯.)
- User-selectable assets that arenβt available forΒ
UIImagePickerController
UIImagePickerController μ μ¬μ©ν μ μλ μ¬μ©μμ ν κ°λ₯ν μμ
- Configuration of the picker to display only Live Photos
Live Photos λ§ νμνλ picker ꡬμ±
- Availability ofΒ PHLivePhotoΒ objects without library access
λΌμ΄λΈλ¬λ¦¬ μ‘μΈμ€ μμ΄ PHLivePhoto(Live Photo) κ°μ²΄ μ¬μ©κ°λ₯
- Stricter validations against invalid inputs
μ ν¨νμ§ μλ μ λ ₯μ λν λ μ격ν κ²μ¦
μ΄λ κ² λ³΄λκΉ κΈ°λ₯λ©΄μμ 무μμ΄ νμ€ν λ€λ₯Έμ§ λͺ¨λ₯΄κ² λλ°μ! λ§λ€μ΄λ³΄κΈ°μ μ λ¨Όμ μκ°ν΄λ³΄κ² μ΅λλ€!
- multiple select
- zoom in or out
- search
- κΆν μμ² νμ μ΄ λ¨μ§ μλλ€.
μμ²..λμ§ μλμ..? νλ₯κ·Έλ
import PhotosUI
: picker 뷰컨νΈλ‘€λ¬λ₯Ό ꡬμ±νλ μ 보λ₯Ό ν¬ν¨ν κ°μ²΄μ λλ€.
μ΄ κ°μ²΄λ‘ μ μ΄ ν μ μλλ° κ·Έ μ’ λ₯λ₯Ό μμ보μ!
var configuration = PHPickerConfiguration()
// π selectionLimit
// π μ μ κ° μ νν μ μλ μμ
μ μ΅λ κ°―μ. κΈ°λ³Έκ° 1. 0 μ€μ μ μ νμ μμ€ν
μ΄ μ§μνλ μ΅λκ°μΌλ‘ μ€μ .
configuration.selectionLimit = 1
// π filter
// π picker κ° νμνλ μμ
νμ
μ νμ μ μ©. κΈ°λ³Έμ μΌλ‘ λͺ¨λ μμ
μ νμ νμ(μ΄λ―Έμ§, λΌμ΄λΈν¬ν , λΉλμ€)
configuration.filter = .images
// configuration.filter = .any(of: [.images, .livePhotos, .videos])
λ§λ PHPickerConfiguration μ κ°μ§κ³ PHPickerViewController λ₯Ό λ§λ€μ΄μΌ ν©λλ€.
let picker = PHPickerViewController(configuration: configuration)
UIImagePickerController
λ μ ννκ³ didFinishPickingMediaWithInfo
λ©μλλ‘ μ νν λ―Έλμ΄μ μ 보λ₯Ό κ°μ Έμλλ° PHPicker λ λμΌν μν μ΄ μλ€.
// π μ μ κ° μ νμ μλ£νκ±°λ μ·¨μ λ²νΌμΌλ‘ λ«μμ λ μλ €μ£Όλ delegate
extension ViewController: PHPickerViewControllerDelegate {
// π required method
func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
// ...
}
}
PHPickerViewControllerDelegate
μ μ±νν΄μ£Όκ³ μμλ picker.delegate = self
μ€μ ν΄μ£Όμ΄μΌ νλ€.
μ΄μ νΌμ»€λ₯Ό λ·°μ λμ΄λ΄ μλ€! μλλ μ 체 μ½λμ λλ€.
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
var configuration = PHPickerConfiguration()
// π The maximum number of selections the user can make.
// π κΈ°λ³Έκ° 1. 0 μ€μ μ μ νμ μμ€ν
μ΄ μ§μνλ μ΅λκ°μΌλ‘ μ€μ .
configuration.selectionLimit = 2
// π The filter you apply to restrict the asset types the picker displays.
// π κΈ°λ³Έμ μΌλ‘ μ΄λ―Έμ§(λΌμ΄λΈν¬ν ν¬ν¨), λΌμ΄λΈν¬ν , λΉλμ€μ κ°μ λͺ¨λ μμ
νμ
νμ.
configuration.filter = .images
// configuration.filter = .any(of: [.images, .livePhotos, .videos])
let picker = PHPickerViewController(configuration: configuration)
picker.delegate = self
self.present(picker, animated: true, completion: nil)
}
}
// π μ μ κ° μ νμ μλ£νκ±°λ μ·¨μ λ²νΌμΌλ‘ λ«μμ λ μλ €μ£Όλ delegate
extension ViewController: PHPickerViewControllerDelegate {
// π required method
func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
// ...
}
}
μ΄μ μ νν μμ λ€μ λ€λ£¨μ΄λ³΄κ² μ΅λλ€.
delegate μμ νλΌλ―Έν° results λ₯Ό μ¬μ©νλ©΄λλ΅λλ€!
- PHPickerResult : μ νλ μμ μ λνλ΄λ νμ .
- itemProvider: NSItemProvider. μ νλ μμ μ respresentation.
extension ViewController: PHPickerViewControllerDelegate {
func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
// π μ νμλ£ νΉμ μ·¨μνλ©΄ λ·° dismiss.
picker.dismiss(animated: true, completion: nil)
// π itemProvider λ₯Ό κ°μ Έμ¨λ€.
let itemProvider = results.first?.itemProvider
if let itemProvider = itemProvider,
// π itemProvider μμ μ§μ ν νμ
μΌλ‘ λ‘λν μ μλμ§ μ²΄ν¬
itemProvider.canLoadObject(ofClass: UIImage.self) {
// π loadObject() λ©μλλ completionHandler λ‘ NSItemProviderReading κ³Ό error λ₯Ό μ€λ€.
itemProvider.loadObject(ofClass: UIImage.self) { image, error in
// π itemProvider λ background asnyc μμ
μ΄κΈ° λλ¬Έμ UI μ κ΄λ ¨λ μ
λ°μ΄νΈλ κΌ main μ°λ λμμ μ€νν΄μ€μΌ ν©λλ€.
DispatchQueue.main.sync {
self.myImageView.image = image as? UIImage
}
}
}
}
}
λ€μκ³Ό κ°μ΄ PHPickerResult
λ°°μ΄μμ κΊΌλ΄μ£Όλ©΄ λλ€.
func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
picker.dismiss(animated: true, completion: nil)
let itemFirstProvider = results[0].itemProvider
let itemSecondProvider = results[1].itemProvider
if itemFirstProvider.canLoadObject(ofClass: UIImage.self) {
itemFirstProvider.loadObject(ofClass: UIImage.self) { image, error in
DispatchQueue.main.sync {
self.myFirstImageView.image = image as? UIImage
}
}
}
if itemSecondProvider.canLoadObject(ofClass: UIImage.self) {
itemSecondProvider.loadObject(ofClass: UIImage.self) { image, error in
DispatchQueue.main.sync {
self.mySecondImageView.image = image as? UIImage
}
}
}
}
μΆμ² :