LoginSignup
0
2

More than 1 year has passed since last update.

SwiftUIでPHPhotoPickerを使用する

Last updated at Posted at 2021-04-29

この記事は何?

PHPhotoPickerをSwiftUIで使用するアプリを作成します。

スクリーンショット 2021-04-29 13.15.34.png

実行環境

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ネイティブになったらいいなー。

0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2