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
変更はガイドラインに沿ってないのかなぁ…?
一旦このやり方で解決はしたけど、もっと楽な方法とかありそう。