15
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

PHPickerをStoryBoard,SwiftUIで使う

Last updated at Posted at 2020-07-27

PHPickerとは

WWDC2020で新しいImagePickerが発表されました。
UIImagePickerControllerに代わる新しいデフォルトのImagePickerです。
検索ができたりアクセス権限を求めないなど今までとは違った挙動ですが詳細は省きます。

動作環境

macOS 10.15.6
Xcode 12 beta 1
iOS 14 beta 1

使い方

// Pickerの設定
var config = PHPickerConfiguration(photoLibrary: PHPhotoLibrary.shared())

// Pickerで選択するメディアの種類をフィルタリング
config.filter = .images // videos, livePhotos

// 選択できる数を指定
config.selectionLimit = 3

// configを渡して初期化
let controller = PHPickerViewController(configuration: configuration)

// delegateをセット
controller.delegate = self

// 表示
present(controller, animated: true)

config.filterでPickerに表示されるメディアを選択できます。
現時点で .images, videos, livePhotosが確認できました。

config.selectionLimitでPickerで選択できる数値を決められます。
便利ですね。

PHPickerViewControllerDelegateの設定

extension ViewController: PHPickerViewControllerDelegate {
    // Pickerを閉じたときにコールされる
    public func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
        for image in results {
            // PHPickerResultからImageを読み込む
            image.itemProvider.loadObject(ofClass: UIImage.self) { (selectedImage, error) in
                if let error = error {
                    print("error: \(error.localizedDescription)")
                    return
                }
                // UIImageに変換
                guard let wrapImage = selectedImage as? UIImage else {
                    print("wrap error")
                    return
                }

                // 選択されたimageを保管しておく
                self.selectedImages.append(wrapImage)
            }
        }
    }
}

SwiftUIでの使用方法

import SwiftUI
import PhotosUI

struct ImageSelectView: View {
    // Pickerの表示/非表示フラグ
    @State private var isPresented = false
    // Imageを格納
    @State var pickerResult = UIImage(named: "defaultImage")!
    // PHPickerの設定
    var config: PHPickerConfiguration {
       var config = PHPickerConfiguration(photoLibrary: PHPhotoLibrary.shared())
        config.filter = .images
        config.selectionLimit = 1
        return config
    }

    var body: some View {
        VStack(alignment: .leading) {
            Button("Image Picker") {
                // isPresentedを切り替える
                isPresented.toggle()
            }.sheet(isPresented: $isPresented) {
                // Pickerを初期化
                PhotoPicker(configuration: self.config,
                            pickerResult: $pickerResult,
                            isPresented: $isPresented)
            }
            // 選択したImageを表示する
            Image.init(uiImage: pickerResult)
                .renderingMode(.original)
                .resizable()
                .frame(width: UIScreen.main.bounds.width, height: 250, alignment: .center)
                .scaledToFill()
        }
    }
}
// PHPickerViewControllerをSwiftUIで表示するためのクラス
// 参考 https://dev.classmethod.jp/articles/tried-swiftui-tutorial-secondpart/
struct PhotoPicker: UIViewControllerRepresentable {
    let configuration: PHPickerConfiguration
    @Binding var pickerResult: UIImage
    @Binding var isPresented: Bool

    func makeUIViewController(context: Context) -> PHPickerViewController {
            let controller = PHPickerViewController(configuration: configuration)
            controller.delegate = context.coordinator
            return controller
    }

    func updateUIViewController(_ uiViewController: PHPickerViewController, context: Context) {

    }

    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }

    /// PHPickerViewControllerDelegate => Coordinator
    class Coordinator: PHPickerViewControllerDelegate {
        private let parent: PhotoPicker

        init(_ parent: PhotoPicker) {
            self.parent = parent
        }
        // PHPickerViewControllerDelegateの設定
        func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
            for image in results {
                image.itemProvider.loadObject(ofClass: UIImage.self) { (selectedImage, error) in
                    if let error = error {
                        print("error: \(error.localizedDescription)")
                        return
                    }
                    guard let wrapImage = selectedImage as? UIImage else {
                        print("wrap error")
                        return
                    }
                    // 選択したImageをpickerResultに格納
                    self.parent.pickerResult = wrapImage
                }
            }
            // 閉じる
            parent.isPresented = false
        }
    }
}

UIKitをSwiftUIで使えるようにするためひと手間必要でした

サンプルはこちら
https://github.com/lcr3/PHPickerSample

15
9
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
15
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?