目次
概要
自身の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)
}
}
こうすることで、写真アプリの画像の一覧を表示して、閉じるということができた。
次は選択した画像を表示するなど、データとして変数に格納することをしてみよう。
参考ページ
- DevelopersIO「【Swift】PHPickerViewControllerをスワイプダウンで閉じないようにする方法」
- Developer Forums「no didCancel in PHPickerViewControllerDelegate?」
- aozisoQ「[SwiftUI]PHPicker+CoreDataで写真を複数選択してアプリに保存する」