
【Swift】PHPickerViewControllerをスワイプダウンで閉じないようにする方法
この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
PHPickerViewControllerをスワイプダウンで閉じないようにする方法を調べたので記事にしておきます。
環境
- Xcode 14.1
- iOS 16.1
iOSデバイスでPHPickerViewControllerを.pageSheetや.formSheetのようなpresentationStyleで表示し、スワイプダウンで閉じさせたくないという対応をしたい時に、通常のViewControllerであればisModalInPresentationをtrueにすれば閉じないように出来るのにPHPickerViewControllerでは機能しませんでした。
試したコード
import UIKit
import PhotosUI
class ViewController: UIViewController {
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
presentPhotoPicker()
}
private func presentPhotoPicker() {
var configuration = PHPickerConfiguration()
configuration.filter = .images
configuration.selectionLimit = 1
let picker = PHPickerViewController(configuration: configuration)
picker.delegate = self
// スワイプダウンで閉じるを出来ないようにする
picker.isModalInPresentation = true
present(picker, animated: true)
}
}
// MARK: - PHPickerViewController Delegate
extension ViewController: PHPickerViewControllerDelegate {
func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
// do something
dismiss(animated: true)
}
}
picker.isModalInPresentation = trueにしているはずなのにしっかり閉じれてしまいます。

PHPickerをViewControllerでラップする
通常のViewControllerだとisModalInPresentationの変更が反映されるので、PHPickerをViewControllerでラップして、そのラップしているViewControllerのisModalInPresentationを変更します。
/// スワイプダウンで閉じれないPHPickerViewController
private class SwipeDownDisablePHPickerViewController: UIViewController {
init(picker: PHPickerViewController) {
super.init(nibName: nil, bundle: nil)
// スワイプダウンで閉じるを出来ないようにする
isModalInPresentation = true
addChild(picker)
picker.didMove(toParent: self)
view.addSubview(picker.view)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
あとは、呼び出し時にスワイプダウンで閉じれないPHPickerViewControllerを生成して、表示してあげるだけです。
import UIKit
import PhotosUI
class ViewController: UIViewController {
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
presentPhotoPicker()
}
private func presentPhotoPicker() {
var configuration = PHPickerConfiguration()
configuration.filter = .images
configuration.selectionLimit = 1
let picker = PHPickerViewController(configuration: configuration)
picker.delegate = self
let SwipeDownDisablePicker = SwipeDownDisablePHPickerViewController(picker: picker)
present(SwipeDownDisablePicker, animated: true)
}
}
// MARK: - PHPickerViewController Delegate
extension ViewController: PHPickerViewControllerDelegate {
func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
// do something
dismiss(animated: true)
}
}
isModalInPresentation = trueが機能してスワイプダウンで閉じれなくなりました。
おわりに
UIImagePickerControllerでも同じことが発生するようです。ただかなり特殊な方法なので、PHPickerViewControllerを.fullScreenで表示するや、スワイプダウンで閉じれてもいいように検討するなどしても良いかもしれません。
今回はPHPickerViewControllerだったのでキャンセルボタンを押下するとfunc picker(_ picker:, didFinishPicking)のデリゲートメソッドが呼ばれる為、そこで処理を書けばよいですが、通常のViewControllerの場合に
Apple公式 Disabling the Pull-Down Gesture for a Sheetでは、ユーザーにプレゼンテーションを却下できない理由を説明してUXを向上しましょうとの記載もありました。











