【iOS/SwiftUI】カメラロールの画像を参照する

SwiftUIに戻る

目次

概要

自身のiPhoneに保存している画像をアプリで使いたい時もあるだろう。
その時にはPhotosUIのPHPickerViewControllerを使用する。

また、こちらはSwiftUIで調節使えないため、SwiftUIと橋渡し的な役割をするUIViewControllerRepresentableを継承したクラスが必要になる。

ソースコード

import SwiftUI

@main
struct TestApp: App {
    @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
    
    var body: some Scene {
        WindowGroup {
            PhotoView()
        }
    }
}
import SwiftUI

struct PhotoView: View {
    @ObservedObject private var viewModel = PhotoViewModel()
    
    var body: some View {
        VStack {
            Button {
                viewModel.isShownPhotoList = true
            } label: {
                Text("フォトライブラリ表示")
            }
        }
        .sheet(isPresented: $viewModel.isShownPhotoList) {
            PhotoPickerView {_ in 
                
            }
        }
    }
}
import SwiftUI
import PhotosUI

struct PhotoPickerView: UIViewControllerRepresentable {
    var configuration: PHPickerConfiguration
    let completion: ([PHPickerResult]) -> Void
    
    init(completion: @escaping ([PHPickerResult]) -> Void) {
        configuration = PHPickerConfiguration(photoLibrary: .shared())
        configuration.filter = .images
        configuration.preferredAssetRepresentationMode = .current
        configuration.selectionLimit = 5
        
        self.completion = completion
    }
    
    func makeUIViewController(context: Context) -> PHPickerViewController {
        let controller = PHPickerViewController(configuration: configuration)
        controller.delegate = context.coordinator
        controller.isModalInPresentation = true
        return controller
    }
    
    func updateUIViewController(_ uiViewController: PHPickerViewController, context: Context) {
        
    }
    
    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }
}

class Coordinator: NSObject {
    private var parent: PhotoPickerView
    init(_ parent: PhotoPickerView) {
        self.parent = parent
    }
}

extension Coordinator: PHPickerViewControllerDelegate {
    func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
        if results.isEmpty {
            picker.dismiss(animated: true)
        }
    }
}
import Foundation

class PhotoViewModel: ObservableObject {
    @Published var isShownPhotoList = false
}

デモ動画

詳細

PhotoViewはSwiftUIで写真アプリの画像一覧を表示するためのViewだ。
そして、PhotoPickerViewでSwiftUIとSwiftUIで実装できない部分の橋渡し的なクラスをじっそうしている。
今回のメインとなるのはPhotoPickerView.swiftの部分だ。

PhotoPickerView

まず、ここで写真アプリ一覧を表示した時の設定をしている。

init(completion: @escaping ([PHPickerResult]) -> Void) {
    configuration = PHPickerConfiguration(photoLibrary: .shared())
    configuration.filter = .images
    configuration.preferredAssetRepresentationMode = .current
    configuration.selectionLimit = 5
    
    self.completion = completion
}
func makeUIViewController(context: Context) -> PHPickerViewController {
    let controller = PHPickerViewController(configuration: configuration)
    controller.delegate = context.coordinator
    controller.isModalInPresentation = true
    return controller
}

PHPickerConfiguration

プロパティ内容
filter画像を表示する際、どの一覧を表示するか
preferredAssetRepresentationMode動画を読み込む時に必要
selectionLimit一度に選択できる画像の数

PHPickerViewController

プロパティ内容
isModalInPresentation下方向へのスワイプで写真一覧を閉じるかどうか
trueで閉じられないようにする

Coordinatorのデリゲート部分

ここでキャンセルボタンを押下した時に写真一覧を閉じるようにする。

func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
    if results.isEmpty {
        picker.dismiss(animated: true)
    }
}

こうすることで、写真アプリの画像の一覧を表示して、閉じるということができた。
次は選択した画像を表示するなど、データとして変数に格納することをしてみよう。

参考ページ

SwiftUIに戻る