この記事は何?
PHPhotoPickerをSwiftUIで使用するアプリを作成します。
実行環境
Swift 5.3
Xcode 12.5
macOS 11.3
Photosフレームワーク
「デバイスに保存された写真」を取得するための、プライバシーに配慮した全く新しいフレームワークです。
ハンズオン
順を追って、アプリを作成していきます。
基本の画面
基本画面には「写真を表示するための枠」と「写真ピッカーを開くためのボタン」を配置します。
まずは、「写真を表示する枠」のビューを作成しておきます。
PhotoFrame.swift
import SwiftUI
struct PhotoFrame: View {
@Binding var image: Image?
var body: some View {
if let image = image {
image
.resizable()
.aspectRatio(contentMode: .fit)
} else {
Image(systemName: "photo")
.font(.title)
.foregroundColor(.gray)
}
}
}
次に、「写真ピッカーを開くためのボタン」を作成します。
ShowPickerButton.swift
import SwiftUI
struct ShowPickerButton: View {
@Binding var isShowLibrary: Bool
var body: some View {
Button(action: {
isShowLibrary = true
}, label: {
Text("Choose Photo")
.font(.title2)
.padding()
.background(Color.blue)
.foregroundColor(.white)
.cornerRadius(10.0)
})
}
}
こららのビューを基本画面に配置します。
ContentView.swift
import SwiftUI
struct ContentView: View {
@State private var isShowPhotoLibrary = false
@State var image: Image?
@EnvironmentObject var classifier: ImageClassifier
var body: some View {
ZStack {
PhotoFrame(image: $image)
VStack {
Spacer()
Text(classifier.classificationLabel)
ShowPickerButton(isShowLibrary: $isShowPhotoLibrary)
}
}
.sheet(isPresented: $isShowPhotoLibrary, content: {
PhotoPicker(isPresented: $isShowPhotoLibrary,
seledtedImage: $image)
})
}
}
写真ピッカーのビューを作成する
UIKitのビューコントローラをSwiftUIで使用するは、ViewControllerRepresentableプロトコルに適合した構造体でラップします。
PhotoPicker.swift
import SwiftUI
import PhotosUI
struct PhotoPicker: UIViewControllerRepresentable {
@Binding var isPresented: Bool
@Binding var seledtedImage: Image?
func makeUIViewController(context: Context) -> PHPickerViewController {
var configuration = PHPickerConfiguration()
configuration.filter = .images
let picker = PHPickerViewController(configuration: configuration)
picker.delegate = context.coordinator
return picker
}
func updateUIViewController(_ uiViewController: PHPickerViewController, context: Context) {
// do nothing.
}
}
PhotoPicker型を定義する
デリゲートメソッドを介してPhotoPickerViewControllerとやり取りするには、仲介役となるCoordinatorクラスを定義する必要があります。
PhotoPicker.swift
コーディネーターを定義する
このクラスは、PhotoPicker構造体のネスト型として定義します。
Coordinatorクラス
import SwiftUI
import PhotosUI
struct PhotoPicker: UIViewControllerRepresentable {
@Binding var isPresented: Bool
@Binding var seledtedImage: Image?
func makeUIViewController(context: Context) -> PHPickerViewController {...}
func updateUIViewController(_ uiViewController: PHPickerViewController, context: Context) {
// do nothing.
}
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
class Coordinator: PHPickerViewControllerDelegate {
private let parent: PhotoPicker
init(_ parent: PhotoPicker) {
self.parent = parent
}
func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
parent.isPresented = false
let itemProvider = results.first?.itemProvider // itemProvider is NSItemProvider? Type.
if let itemProvider = itemProvider, itemProvider.canLoadObject(ofClass: UIImage.self) {
itemProvider.loadObject(ofClass: UIImage.self) { (image, error) in
if let uiImage = image as? UIImage {
self.parent.seledtedImage = Image(uiImage: uiImage)
}
}
}
}
}
}
最後に
WWDC2021で、PHPickerViewがSwiftUIネイティブになったらいいなー。