- Published on
๐ฑ iOS - PHPicker
- Authors
- Name
- ์ด์ฐฝ์ค
ํ ์ด ํ๋ก์ ํธ๋ฅผ ์งํํ๋ ์ค์ ์ด๋ฏธ์ง๋ฅผ ์ ํํด์ ์ ๋ก๋ํ๋ ๋์์ด ํ์ํ์ต๋๋ค.
๋น์ฐํ ์ฒ์์๋ ์๋ฃ๊ฐ ๋ง์ UIImagePickerController
๋ฅผ ์ฌ์ฉํ๊ณ ์ ํ์ต๋๋ค.
์ด ๋๋ PHPicker
๋ผ๋ API๊ฐ ์๋์ง๋ ๋ชฐ๋์์ฃ .
๊ธฐ๋ฅ์ด ๊ต์ฅํ ์ ํ์ ์ด๋ผ๋ ์ฌ์ค์ ํํํ๋ฉฐ ๊ณต๋ถ๋ฅผ ํ๋ ์ค์ iOS14์ ๊ธฐ์กด์ UIImagePickerController
๋ฅผ ๋์ฒดํ๊ณ ์ PHPicker
๊ฐ ๋ฑ์ฅํ๋ค๋ ์์์ ์ ํ๊ฒ ๋์ต๋๋ค.
๊ธฐ๋ณธ ์ฌ์ง ์ฑ์ ์๋ ๋ค์ค์ ํ/์ค์ธ์์/๊ฒ์ ๊ธฐ๋ฅ์ด ํฌํจ๋์ด ์๋ค๊ณ ํ๋ค์..! ๐ซข
PhotoKit
์ฌ์ค ์ด PHPicker
๋ผ๋ ๋.. ํผ์ ๋กํ๋ ๋ฑ์ฅํ๋ ๊ฑด ์๋๋๋ค.
์ ํ์ด ๋ผ์ด๋ธ ํฌํ ๋ฑ์ ์ถ๊ฐํ๋ฉฐ ์ฌ์ง๊ณผ ๋น๋์ค ๊ธฐ๋ฅ์ ํ์ ์ฃผ๊ธฐ ์ํด ๊ฐ๋ฐํ PhotoKit
์ ํฌํจ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ค ์ค ํ๋์
๋๋ค.
์ญ์ ๊ณต์ ๋ฌธ์๊ฐ ์ ๋ณด๋ฅผ ์ฐพ๊ธฐ์ ๊ฐ์ฅ ์ข๊ฒ ์ฃ ?
์๋ก์ด API๋ฅผ ์๊ฐํ๋ WWDC์์๋ ๋น์ฐํ ์๊ฐํ๋ ์ ์ด ์์ต๋๋ค.
WWDC2020 - Meet the new Photos picker
์ธ์ ์ ๋ชฉ์๋ **โPhotosโ**๋ผ๊ณ ๊ฐ์กฐ๋ฅผ ํด๋์๋ค์.
๊ฐ๋ฐ์๋ค์ด ์ผ๋ง๋ ์ฌ๋ฌ ์ฌ์ง ์ ํ์ ์๊ตฌํ์๋์ง ํ์ธํ ์ ์๋ ๋๋ชฉ์ด ์๋๊ฐ ์ถ์ต๋๋ค.
์ด์ง์ฟต 2021๋ ๊ณผ 2022๋ ์ธ์ ์์๋ ์๊ฐ๋ ๋ด์ฉ์ ์ดํด๋ณด๋, 2021๋ ์๋ ProRAW ํฌ๋งท ์๊ฐ์ ํ์ ์ค ๋งํผ ์๋ก์ด ํฌ๋งท ์ง์์ ์๊ฐํ๊ณ 2022๋ ์๋ ์ค๋ฆฌ์ฝ ๋งฅ๊ณผ ํจ๊ป ๋ก์ํ macOS์์๋ PHPicker๋ฅผ ์ ๋๋ก ์ง์ํ๋ค๋ ๋ด์ฉ๋ค์ด ์๋ค์.
์ด๋ฏธ ๊ธฐ์กด์ UIImagePicker
๋ฅผ ์์ ํ ๋์ฒดํ ๊ฒ ๊ฐ์ต๋๋ค.
์ ๊ทธ๋์ ํต์ฌ์ ๋ญ๋..?
PHPicker
๋ PhotoKit
์ค์์๋ PhotosUI ํ๋ ์์ํฌ์ ํฌํจ๋์ด ์๊ธฐ ๋๋ฌธ์ ์ฌ์ฉํ๋ ค๋ฉด PhotosUI
๋ฅผ import
ํด์ผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
import PhotosUI
Photos Picker์ ์ด์
๊ทธ๋์ ์ ํ์ ์ Photos Picker
(PHPicker
)๋ฅผ ์ฌ์ฉํด์ผ ํ๋ค๊ณ ํ ๊น์?
๊ธฐ์กด์ UIImagePicker
์ ๋์๋๋ 6๊ฐ์ง ์ด์ ์ ๋ด์ธ์ฐ๊ณ ์์ต๋๋ค.
- ์ด๋ฏธ์ง ๋ก๋ฉ์ ์ง์ฐ๊ณผ ๋ณต๊ตฌ UI
- RAW์ ํ๋ ธ๋ผ๋ง ์ด๋ฏธ์ง ๋ฑ์ ํฌ๊ณ ๋ณต์กํ ์ ์ ์ ์์ ํ๊ฒ ํธ๋ค๋ง
UIImagePickerController
์์๋ ๋ถ๊ฐ๋ฅํ ์ ์ ์ ํ ์ต์ - ๋ผ์ด๋ธ ํฌํ ๋ง์ ์ ํํ ์ ์๋ ์ค์ ์ ๊ณต
- ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ ๊ทผ ์์ด PHLivePhoto ๊ฐ์ฒด ์ฌ์ฉ ๊ฐ๋ฅ
- ์ ํจํ์ง ์์ ์ ๋ ฅ์ ๋ํ ๊น๋ค๋ก์ด validation
๊ธฐ์กด์ ์ฑ๋ค์ ํธ๋ํฐ์ ์ ์ฅ๋ ์ฌ์ง๋ค์ ์ ๊ทผํ๊ธฐ ์ํด์ ์ ๊ทผ ์์ฒญ์ ํ์์ฃ ?
์ ์ฌ์ง์ฒ๋ผ์.
ํ์ง๋ง ์๋ก์ด PHPicker
๋ฅผ ์ฌ์ฉํ๋ฉด ํ๋กํ ์ฌ์ง ์ ํ๋ฑ์ ๋จ์ํ ์ฌ์ง ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์์
์ผ๋ก๋ ๊ถํ์ ์๊ตฌํ์ง ์๋๋ค๊ณ ํฉ๋๋ค.
์ฌ์ง ํธ์ง, ์นด๋ฉ๋ผ ์ฑ๋ฑ์ ์ฌ์ ํ ๊ถํ์ ์๊ตฌํ๋ค๊ณ ํ๋ค์.
๋ํ ์ฌ์ง์ ๋จ์ํ ์ ์ฅํ๋ ์์ ๋ํ ์ฌ์ง ์ ์ฅ ๊ถํ์ด๋ผ๋ ๋ฎ์ ๋ ๋ฒจ์ ๊ถํ๋ง์ ๋ถ์ฌํด์ ์ฌ์ฉ์์ ์์ดํฐ์ ๋ ์์ ํ๊ฒ ์งํฌ ์ ์๋ค๊ณ ํฉ๋๋ค.
๊ฐ์ฅ ์ค์ํ ์ ์ ๋ณด์์์์ ๋๋ค.
PHPicker
๋ ์ํํธ์จ์ด์ ์ธ ์บก์ฒ์์ ์์ ํฉ๋๋ค.
์คํฌ๋ฆฐ์ท์ ์ฐ์ ๋ ๋ชจ๋ ์ปจํ ์ธ (์ฌ์ง, ๋น๋์ค)๋ค์ ๋ ๋๋งํ์ง ์์ ์ํ๋ก ์บก์ฒํ์ฌ ๋ถ๋ฒ ํ๋ก๊ทธ๋จ์ผ๋ก ์ธํด ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ์บก์ฒ๋์ด ๊ฐ์ธ ์ ๋ณด๊ฐ ์ ์ถ๋๋ ๊ฒ์ ๋ง์ ์ ์๋ค๊ณ ํฉ๋๋ค.
์ด๊ฒ ์ด๋ป๊ฒ ๊ฐ๋ฅํ ๊ฒ์ด๋?
PHPicker
๋ ์ฑ ์์์ ์คํ๋๋ ๊ฒ ๊ฐ์ UI๋ฅผ ๊ฐ์ง๋ง ์ฌ์ค์ ๋
๋ฆฝ๋ ๋ค๋ฅธ ํ๋ก์ธ์ค์
๋๋ค. ์ ์ฌ์ง์์์ฒ๋ผ์.
์ฑ์ ๋ชจ์์ ๊ทธ์ ๋ ๋๋งํ์ฌ ๋ฐฐ๊ฒฝ์ผ๋ก ๋ณด์ฌ์ฃผ๊ณ ์๋ ๊ฒ์ด์ฃ .
๋ฐ๋ผ์ ์ฑ์ PHPicker
์ ๊ธฐ๋ฅ๋ค์ ์ง์ ์ฌ์ฉํ๊ณ ์๋ ๊ฒ์ด ์๋๋ผ, PHPicker
๋ ๋ฐ๋ก ๋์ํ๊ณ ์ ์ ๊ฐ ์ ํํ ์ปจํ
์ธ ๋ค์ ํํด์๋ง ์ ๋ณด๋ฅผ ์ ๊ณตํ๋ ๊ฒ์
๋๋ค.
PHPickerViewController
์ ์ฌ์ง์์ ์ ์ ์๋ฏ์ด PHPickerViewController
๋ PHPickerConfiguration
์ ํตํด ์์ฑ๋๊ณ ์ ์ดํ ์ ์์ต๋๋ค.
var configuration = PHPickerConfiguration()
filter์ selectionLimit
filter
ํ๋กํผํฐ๋ก๋ PHPicker
์์ ์ ํํ ์ ์๋ ์ปจํ
์ธ ํ์
์ ์ ํด์ค ์ ์์ต๋๋ค.
images
, livePhotos
, videos
, screenshots
๋ฑ ๋ค์ํ ์ต์
์ ์ง์ํ๊ณ ์๊ณ , ๋ฐ๋ก ์ง์ ํด์ฃผ์ง ์๋๋ค๋ฉด ๊ธฐ๋ณธ๊ฐ์ผ๋ก .all
๊ฐ์ ๊ฐ์ต๋๋ค.
configuration.filter = .images
configuration.filter = .any(of:
[.images, .livePhotos, .videos]
)
selectionLimit
ํ๋กํผํฐ๋ก๋ ์ ํํ ์ด๋ฏธ์ง์ ๊ฐ์๋ฅผ ์ ํด์ค ์ ์์ต๋๋ค.
๊ธฐ๋ณธ๊ฐ์ 1์ด๊ณ , ์์์ ๊ฐ์ ๋ฃ์ผ๋ฉด ์ฑ์ด ํฌ๋์ฌ๋ฉ๋๋ค.
numberOfLines
์ ๊ฐ์ด 0์ ๊ฐ์ ๋ฃ์ด์ฃผ๋ฉด ์ ํ ๊ฐ์๋ฅผ ์ ํ ์์ด ์ค์ ํด์ค ์ ์์ต๋๋ค.
configuration.selectionLimit = 12
์ด๋ ๊ฒ ์ค์ ํด์ค configuration
๊ฐ์ PHPickerViewController
์ ํ๋ผ๋ฏธํฐ๋ก ๋ฃ์ด์ฃผ์ด ์ ์ฉํฉ๋๋ค.
let imagePicker = PHPickerViewController(configuration: configuration)
imagePicker.delegate = self
present(imagePicker, aniamted: true)
UIImagePickerController
์ ๋ง์ฐฌ๊ฐ์ง๋ก delegate
๊น์ง ์์ํด์ฃผ๊ณ present
ํ๋ฉด ์ฌ์ง์ ๊ณ ๋ฅผ ์ ์๋ ํ๋ฉด์ด present
๋ฉ๋๋ค.
์ ํ ๊ฒฐ๊ณผ ํธ๋ค๋ง
์ ์ ๊ฐ ์ปจํ ์ธ ๋ฅผ ์ ํํ๋ค๋ฉด ํด๋น ์ปจํ ์ธ ๋ค๋ก ๋ฌด์ธ๊ฐ๋ฅผ ํด์ผ๊ฒ ์ฃ .
PHPicker
๋ delegate
์ ๋ฉ์๋๋ฅผ ํตํด ๊ฒฐ๊ณผ๋ฅผ ์ฒ๋ฆฌํด์ค ์ ์์ต๋๋ค.
PHPickerViewControllerDelegate
ํ๋กํ ์ฝ์ ์ฑ์ฉํด์ฃผ๊ณ ,
extension DefaultImagePickerCoordinator: PHPickerViewControllerDelegate {
func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
// do something
}
}
์ ์ ๊ฐ ์ ํ์ ์๋ฃํ๋ค๋ ๋ฒํผ์ ํญํ๋ฉด ํธ์ถ๋๋ picker(_,didFinishPicking)
ํจ์๋ฅผ ๊ตฌํํด์ค๋๋ค.
func picker(_ picker: PHPickerViewController, didFinishPicking reuslts: [PHPickerResult]) {
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
if let image = image {
// do something
}
}
}
}
์ฐ์ picker.dismiss(animated:)
๋ก PHPickerView
๋ฅผ dismiss
ํด์ค๋๋ค.
๊ทธ ํ NSItemProvider
๋ผ๋ ๊ฐ์ฒด๋ก๋ถํฐ ์ ์ ๊ฐ ์ ํํ ์ปจํ
์ธ ๋ฅผ ์ ๊ณต๋ฐ์ ์ ์๋๋ก ์ด๊ธฐํ ๊ณผ์ ๊ณผ ์ค์ ๋ก ๋ถ๋ฌ์ค๋ ๊ณผ์ ์ ๋ฃ์ด์ค๋๋ค.
์ด ๊ณผ์ ์ ๋ด๋ถ์ ์ผ๋ก async
ํ๊ฒ ๊ตฌํ๋์ด ์๊ธฐ ๋๋ฌธ์ @escaping
ํด๋ก์ ์์์ ์ด๋ฏธ์ง๋ฅผ ๋ฐ์ ์ฒ๋ฆฌํด์ฃผ์ด์ผ ํฉ๋๋ค.
๋จ์ํ ์ด๋ฏธ์ง๋ ๋น๋์ค๋ฅผ ์ ํํด์ ๋ฐ์์ค๋ ์์ ์ ์ด๊ฒ๋ง์ผ๋ก๋ ์ถฉ๋ถํฉ๋๋ค.
์ฌ๊ธฐ๊น์ง์ ์์ ์ ์ฌ์ง ์ ๊ทผ ๊ถํ์ ์๊ตฌํ์ง ์์ง๋ง ์ฌ์ง์ ํธ์งํ๋ ๋ฑ์ ์์ ๋ฑ์ ์ฌ์ง ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๊ถํ์ ์๊ตฌํ๊ณ , PhotoKit์ ๋ค๋ฅธ API๋ฅผ ํ์ฉํ์ฌ ์์ ํด์ผํฉ๋๋ค.
๋ง๋ฌด๋ฆฌ
์ค๋์ ์ฐ์ ์ฌ๊ธฐ๊น์ง ์์๋ณด์์ต๋๋ค.
์ ํ์ ์ด๋ฏธ UIImagePickerView
๋ฅผ deprecated ์์ผฐ์ต๋๋ค.
๊ตฌ๊ธ ๊ฒ์ ๊ฒฐ๊ณผ๋ ์์ง ์ด์ ๊ฒ์๋ฌผ๋ค์ ์๋จ์ ๋ ธ์ถ์ํค๊ณ ์์ด WWDC ์ธ์ ์ ์ฐพ์๋ณด์ง ์์๋ค๋ฉด ์ฌ์ ํ ํค๋งค๊ณ ์์์ ๊ฒ ๊ฐ์ต๋๋ค.
ํํํ WWDC ๊ตฌ์๊ตฌ์์ ์ดํด๋ณด๋ ์ต๊ด์ ๊ฐ์ง์๋ค!