🙌

SwiftUIでUIImagePickerControllerを使う

2021/03/19に公開

カメラやライブラリから写真を取り出すUIImagePickerControllerをSwiftUIで使うことが多いのでコピペで使えるように。

環境

  • Xcode 12.4
  • iOS 14.4

ImagePickerView.swift

UIImagePickerControllerUIKitのコンポーネントなのでUIViewControllerRepresentableを使ってSwiftUIから呼び出せるようにする。

ImagePickerView.swift
import SwiftUI

struct ImagePickerView: UIViewControllerRepresentable {
    typealias UIViewControllerType = UIImagePickerController
    @Environment(\.presentationMode) var presentationMode
    @Binding var image: UIImage?
    enum SourceType {
        case camera
        case library
    }
    var sourceType: SourceType
    var allowsEditing: Bool = false

    class Coordinator: NSObject, UINavigationControllerDelegate, UIImagePickerControllerDelegate {
        let parent: ImagePickerView

        init(_ parent: ImagePickerView) {
            self.parent = parent
        }

        func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) {
            if let image = info[.editedImage] as? UIImage {
                parent.image = image
            } else if let image = info[.originalImage] as? UIImage {
                parent.image = image
            }
            parent.presentationMode.wrappedValue.dismiss()
        }
    }

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

    func makeUIViewController(context: Context) -> UIImagePickerController {
        let viewController = UIImagePickerController()
        viewController.delegate = context.coordinator
        switch sourceType {
        case .camera:
            viewController.sourceType = UIImagePickerController.SourceType.camera
        case .library:
            viewController.sourceType = UIImagePickerController.SourceType.photoLibrary
        }
        viewController.allowsEditing = allowsEditing
        return viewController
    }

    func updateUIViewController(_ uiViewController: UIImagePickerController, context: Context) {
    }
}

コードの説明は割愛、ポイントのみ

  • 引数のSourceTypecameralibraryを選択する
    • cameraを使うときはInfo.plistNSCameraUsageDescriptionを追加すること
  • allowsEditingUIImagePickerControllerが提供している編集機能が利用可能

利用

利用するコードの例はこちら。

ContentView.swift
import SwiftUI

struct ContentView: View {
    @State var showingPicker = false
    @State var image: UIImage?
    var body: some View {
        VStack {
            if let image = image {
                Image(uiImage: image)
                    .resizable()
                    .aspectRatio(contentMode: .fit)
            }
            Text("Image")
                .onTapGesture {
                    showingPicker.toggle()
                }
        }
        .sheet(isPresented: $showingPicker) {
            ImagePickerView(image: $image, sourceType: .library)
        }
    }
}

カメラを使い、編集を有効にする場合の呼び出し例はこちら

ImagePickerView(image: $image, sourceType: .camera, allowsEditing: true)

備考

UIImagePickerControllerからフォトライブラリへのアクセスはiOS14でdeprecatedになりました。

UIImagePickerController.SourceType.photoLibrary
Specifies the device’s photo library as the source for the image picker controller.
Deprecated
Use PHPickerViewController instead.

iOS14以降をターゲットにする場合はPHPickerViewControllerを使用した方が良いようです。
https://developer.apple.com/documentation/photokit/phpickerviewcontroller

参考

https://developer.apple.com/documentation/swiftui/uiviewcontrollerrepresentable

Overview
Use a UIViewControllerRepresentable instance to create and manage a UIViewController object in your SwiftUI interface.

Discussion