TL;DR
表示中のUIImagePickerControllerのsourceType変更はうまく動かない
→ カメラ起動、フォトライブラリ起動でボタンを分けて先にsourceType決めさせる
→ またはインスタンス再生成する
やりたいこと
カメラを起動して撮影した画像を取得したい。
また、オプションとしてフォトライブラリ内からも画像を選択できるようにしたい。
やったこと
実装方針
UIImagePickerControllerでカメラを起動
フォトライブラリボタンがタップされたらUIImagePickerControllerのsourceTypeをcameraからphotoLibraryに変更する
ソース
本来はUIImagePickerControllerのcameraOverlayViewを使用して
カメラ表示中にフォトライブラリボタンを設ける予定だが、
とりあえずテストのためpickerのキャンセルボタンでsourceType切り替えを実装
import UIKit
import Photos
class FirstViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
var picker: UIImagePickerController!
override func viewDidLoad() {
super.viewDidLoad()
// 許可リクエスト
AVCaptureDevice.requestAccess(for: AVMediaType.video) { (Bool) in
return
}
}
/// Picker起動ボタン
///
/// - Parameter sender:
@IBAction func btn1_TouchUpInside(_ sender: Any) {
pickerInit(type: UIImagePickerController.SourceType.camera)
}
/// Picker初期化
///
/// - Parameter type: sourceType
func pickerInit(type: UIImagePickerController.SourceType){
self.picker = UIImagePickerController()
self.picker.sourceType = type
self.picker.delegate = self
self.picker.navigationBar.tintColor = UIColor.white
self.picker.navigationBar.barTintColor = UIColor.gray
present(self.picker, animated: false, completion: nil)
}
// MARK: - UIImagePickerControllerのデリゲートメソッド
/// 画像選択時
///
/// - Parameters:
/// - picker:
/// - info:
private func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
// モーダルビューを閉じる
self.picker.dismiss(animated: true, completion: nil)
}
/// キャンセル時
///
/// - Parameter picker:
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
// 表示中のpickerのsourceTypeを切り替えるだけ
if picker.sourceType == UIImagePickerController.SourceType.photoLibrary {
self.picker.sourceType = UIImagePickerController.SourceType.camera
}
else {
self.picker.sourceType = UIImagePickerController.SourceType.photoLibrary
}
}
}
結果
スクショ
!!!?!?!!???!!?!??!?!???wwwwwwwww
カメラは普通なのにフォトライブラリ2回目表示すると何も出ない!なんやこれ!!
調査
レイアウト見てみるか…(最近覚えた)
1.正常時
2.異常時
PUPhotoPickerHostViewControllerが消えた…!?
ていうか誰?誰なの?怖いよぉ!
ググっても出てこないし結局見てもよくわかりませんでした。
じゃあどうするか
一回作ったUIImagePickerControllerでコロコロsourceType変えてるのがまずいと予想。
写真撮影とフォトライブラリからの選択はボタン分けてるアプリばっかりだし。
実装方針
UIImagePickerControllerでカメラを起動
フォトライブラリボタンがタップされたら表示中のUIImagePickerControllerのsourceType変更ではなく、sourceTypeを変更したUIImagePickerControllerインスタンスを新規で生成する。
ソース
本来はカメラ表示中にフォトライブラリボタンを設ける予定だが以下略
import UIKit
import Photos
class SecondViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate{
var picker: UIImagePickerController!
override func viewDidLoad() {
super.viewDidLoad()
// 許可リクエスト
AVCaptureDevice.requestAccess(for: AVMediaType.video) { (Bool) in
return
}
}
/// Picker起動ボタン
///
/// - Parameter sender:
@IBAction func btn1_TouchUpInside(_ sender: Any) {
pickerInit(type: UIImagePickerController.SourceType.camera)
}
/// Picker初期化
///
/// - Parameter type: sourceType
func pickerInit(type: UIImagePickerController.SourceType){
self.picker = UIImagePickerController()
self.picker.sourceType = type
self.picker.delegate = self
self.picker.navigationBar.tintColor = UIColor.white
self.picker.navigationBar.barTintColor = UIColor.gray
present(self.picker, animated: false, completion: nil)
}
// MARK: - UIImagePickerControllerのデリゲートメソッド
/// 画像選択時
///
/// - Parameters:
/// - picker:
/// - info:
private func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
// モーダルビューを閉じる
self.picker.dismiss(animated: true, completion: nil)
}
/// キャンセル時
///
/// - Parameter picker:
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
// 一旦表示中のモーダルを閉じる
self.picker.dismiss(animated: false, completion: nil)
// sourceTypeを切り替えて再度インスタンス生成から行う
if picker.sourceType == UIImagePickerController.SourceType.photoLibrary {
pickerInit(type: UIImagePickerController.SourceType.camera)
}
else {
pickerInit(type: UIImagePickerController.SourceType.photoLibrary)
}
}
}
結果
何度切り替えを行なっても正常にカメラ、フォトライブラリが表示されるようになりました。
まとめ
ぶっちゃけ要因はよくわかりませんでした。
表示中のUIImagePickerControllerのsourceType変更はガイドラインに沿ってないのかなぁ…?
一旦このやり方で解決はしたけど、もっと楽な方法とかありそう。



