MILLEN BOX

音楽好きの元組み込みソフトエンジニアによるプログラミング(主にiOSアプリ開発)の勉強の記録

カメラロールの内容を表示し選択した画像を表示する方法 [swift2.0] [UIImagePickerController]

こんにちは。
本日は自作アプリからiOSのカメラロールへアクセスする方法と選択した画像を表示する方法を書きたいと思います。
完成イメージは以下。
f:id:anthrgrnwrld:20151027183854g:plain

Githubは以下です。
github.com

参考にしたサイトは以下です。
▶︎【iOS】【Swift】写真をその場で撮ったり選択したりする - Qiita

では行きましょう。

自分ポイント0 (準備)

Storyboardにて、カメラロールを表示するためのボタンと、
カメラロールで選択した写真を表示するUIImageViewを追加しておきましょう。
そしてそいつらをいつものようにソースコードへビューっと引っ張っといて下さい。

class ViewController: UIViewController {

    @IBOutlet weak var imageFromCameraRoll: UIImageView!    //写真表示用のUIImageView
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    /**
    カメラロールボタンを押した時
    */
    @IBAction func pressCameraRoll(sender: AnyObject) {

    }

}

自分ポイント1

まずボタンを押したらカメラロールを表示するようにしましょう。
以下のソースコードが該当部分です。
注意点ですが、ViewControllerに以下を追加するのを忘れないこと。

  • UIImagePickerControllerDelegate
  • UINavigationControllerDelegate

コメントは割と書いたつもりなのですが、分からなければ
「カメラロールを表示するためのパーツ」としてコピペでもいいのでは と私は思います。

(追記)
読んで頂いた方からライブラリ呼び出す前は .isSourceTypeAvailableをチェックした方がよいよ!
とアドバイスを頂いたため修正しました。(@toshi586014 さん、いつもありがとうございます!)
「カメラロールはシミュレーター/実機に関係なく実装されているもんだしチェック不要だろう」と思ってたんですが、Appleの公式リファレンスに「デバイスにフォトライブラリがあることを前提にしてはいけません。」との記載が...。
ちゃんと読まないとダメですね。。やっぱ。。
▶︎カメラ操作の プログラミング(iOS用)

class ViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {    //追加してね

    ...

    /**
    ライブラリから写真を選択する
    */
    func pickImageFromLibrary() {

        if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.PhotoLibrary) {    //追記

            //写真ライブラリ(カメラロール)表示用のViewControllerを宣言しているという理解
            let controller = UIImagePickerController()
        
            //おまじないという認識で今は良いと思う
            controller.delegate = self
        
            //新しく宣言したViewControllerでカメラとカメラロールのどちらを表示するかを指定
            //以下はカメラロールの例
            //.Cameraを指定した場合はカメラを呼び出し(シミュレーター不可)
            controller.sourceType = UIImagePickerControllerSourceType.PhotoLibrary
        
            //新たに追加したカメラロール表示ViewControllerをpresentViewControllerにする
            self.presentViewController(controller, animated: true, completion: nil)
        }
    }
    

    /**
    カメラロールボタンを押した時
    */
    @IBAction func pressCameraRoll(sender: AnyObject) {
        
        pickImageFromLibrary()  //ライブラリから写真を選択する
        
    }

}

自分ポイント2

カメラロール自体はiOSの組み込み済みの機能で表示してくれます。
次に実装必要なのは、写真を選択後の動作部分です。
以下のソースコードが該当部分となります。
動かすこと優先です。(正直理解しきれていない)
取得したUIImageを自分ポイント0で用意したUIImageViewに入れています。
私の理解についてはソースのコメントを参照のこと。
あ、ちなみにここですけど、ネットに上がっている書き方だとswit2.0ではビルド通らなくなってました。
以下のページを参照して解決しました。
swift - Objective-C method 'imagePickerController:didFinishPickingMediaWithInfo:' - Stack Overflow

class ViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {

    ....
    
    /**
    写真を選択した時に呼ばれる (swift2.0対応)
    
    :param: picker:おまじないという認識で今は良いと思う
    :param: didFinishPickingMediaWithInfo:おまじないという認識で今は良いと思う
    */
    func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo: [String: AnyObject]) {
        
        //このif条件はおまじないという認識で今は良いと思う
        if didFinishPickingMediaWithInfo[UIImagePickerControllerOriginalImage] != nil {
            
            //didFinishPickingMediaWithInfo通して渡された情報(選択された画像情報が入っている?)をUIImageにCastする
            //そしてそれを宣言済みのimageViewへ放り込む
            imageFromCameraRoll.image = didFinishPickingMediaWithInfo[UIImagePickerControllerOriginalImage] as? UIImage


        }
        
        //写真選択後にカメラロール表示ViewControllerを引っ込める動作
        picker.dismissViewControllerAnimated(true, completion: nil)
    }

}

自分ポイント3

このままだと使用するには少々耐え難いものになっています。
表示される画像のアスペクト比がえらいことになっています。
viewDidLoad辺りでUIImageViewに対しcontentModeの設定をしてあげましょう。
contentModeについては以下の過去記事を参照して下さい。
contentModeの設定は、UIImageViewへ画像を放り込む前にしなければいけないので気をつけて下さい。

UIButtonに画像を貼り付ける (ソースコード編 UIViewContentModeで丁度よく) (swift2.0)(UIViewContentMode)(AspectFit) - MILLEN BOX

class ViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {

    ...

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        
        //contentModeを設定
        // http://anthrgrnwrld.hatenablog.com/entry/2015/10/17/123659 参照
        //.ScaleAspectFit
        //.ScaleAspectFill
        //.ScaleToFill
        imageFromCameraRoll.contentMode = .ScaleAspectFit

    }

    ...

}

なんとなく全体的に「おまじない」感が否めませんが、私はこれはこれでいいと思っています。
何よりも動くソースコードが大事で、知識というのはその後についてきても構わないと考えるからです。
ちょっと言い訳臭かったですかねw。