LoginSignup
2
3

More than 1 year has passed since last update.

UIImagePickerController表示中にsourceTypeを切り替える

Last updated at Posted at 2018-10-12

TL;DR

表示中のUIImagePickerControllersourceType変更はうまく動かない
→ カメラ起動、フォトライブラリ起動でボタンを分けて先にsourceType決めさせる
→ またはインスタンス再生成する

やりたいこと

カメラを起動して撮影した画像を取得したい。
また、オプションとしてフォトライブラリ内からも画像を選択できるようにしたい。

やったこと

実装方針

UIImagePickerControllerでカメラを起動
フォトライブラリボタンがタップされたらUIImagePickerControllersourceTypecameraからphotoLibraryに変更する

ソース

本来はUIImagePickerControllercameraOverlayViewを使用して
カメラ表示中にフォトライブラリボタンを設ける予定だが、
とりあえずテストのためpickerのキャンセルボタンでsourceType切り替えを実装

FirstViewController.swift
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
        }
    }
}

結果

スクショ

1.起動時
起動時.PNG

2.Picker起動(カメラ)
カメラ.png

3.sourceType切り替え(フォトライブラリ)
フォトライブラリ.PNG

4.sourceType切り替え(カメラ)
カメラ.png

5.sourceType切り替え(フォトライブラリ)
フォトライブラリ?.PNG

!!!?!?!!???!!?!??!?!???wwwwwwwww
カメラは普通なのにフォトライブラリ2回目表示すると何も出ない!なんやこれ!!

調査

レイアウト見てみるか…(最近覚えた)

1.正常時

スクリーンショット 2018-10-12 12.51.44.png

2.異常時

スクリーンショット 2018-10-12 12.52.28.png

PUPhotoPickerHostViewControllerが消えた…!?
ていうか誰?誰なの?怖いよぉ!

ググっても出てこないし結局見てもよくわかりませんでした。

じゃあどうするか

一回作ったUIImagePickerControllerでコロコロsourceType変えてるのがまずいと予想。
写真撮影とフォトライブラリからの選択はボタン分けてるアプリばっかりだし。

実装方針

UIImagePickerControllerでカメラを起動
フォトライブラリボタンがタップされたら表示中のUIImagePickerControllersourceType変更ではなく、sourceTypeを変更したUIImagePickerControllerインスタンスを新規で生成する。

ソース

本来はカメラ表示中にフォトライブラリボタンを設ける予定だが以下略

SecondViewController.swift
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)
        }
    }
}

結果

何度切り替えを行なっても正常にカメラ、フォトライブラリが表示されるようになりました。

まとめ

ぶっちゃけ要因はよくわかりませんでした。
表示中のUIImagePickerControllersourceType変更はガイドラインに沿ってないのかなぁ…?
一旦このやり方で解決はしたけど、もっと楽な方法とかありそう。

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3