UIImagePickerView解体新書


#追記（2017/2/26）
- shinriyo@githubさんから、「UIImagePickerControllerを使うにはPlistに書くことが必須になった」とのご指摘をいただきました。
- 自分でも確認したいのですが、Swiftから離れてだいぶ経ってしまったので、詳細な追記ができません。
- なので、その点をご留意の上、読んでもらえると幸いです。

#目的
・swiftでこのUIを使う時に、なんとなくの流れを覚えておくための覚書。間違った解釈をしていたらご指摘いただけるとありがたいです。

#そもそもUIImagePickerViewはなんのために使う？
・カメラ、およびアルバムへのアクセス。そしてそこから画像データを引っ張ってくる時など。

#１、使うための下準備
##必要なスーパークラスの継承
・UIImagePickerViewを使うためには`UIImagePickerControllerDelegate`と`UINavigationControllerDelegate`のスーパークラスを継承しておく必要があるので

```swift
import UIKit

class MainViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
	
	//以下略
```
こういう風にしておく

・UITableViewDelegateとは違ってviewDidLoad内でのself指定や、プロトコルが存在しないので、コード的にはこのまま使えちゃう

##必要なUIパーツ
・画像を扱うので、画像を貼り付けるための`UIImageView`の配置は必須
・あとは「カメラを発動」したり「アルバムを見る」ためのアクションを引き起こす`UIButton`なども必要。ただこれはButtonでなくともアクションを引き起こすことができればいいので、そこは自由

#２、実装
##大まかな流れ
・今回のアクションのきっかけは`UIButton`を使用

・まずボタンのアクション関数を作る。

```swift
@IBAction func tapCameraBtn(sender: AnyObject) {

}
```

・次に何のソースにアクセスするかを`UIImagePickerControllerSourceType`で指定しておく

```swift
@IBAction func tapCameraBtn(sender: AnyObject) {
	//カメラにアクセスする場合（例ではこっちの方を使う）
	let sourceType: UIImagePickerControllerSourceType = .Camera
	//アルバムにアクセスする場合
	//let sourceType: UIImagePickerControllerSourceType = .PhotoLibrary
}
```

・今回はカメラの方にアクセスする場合を見る

・次にカメラのソースが使用可能かどうかを判定する

```
@IBAction func tapCameraBtn(sender: AnyObject) {
	let sourceType: UIImagePickerControllerSourceType = .Camera
	
	//使えるかどうかの判定
	if UIImagePickerController.isSourceTypeAvailable(.Camera){
        print("成功")
    }else{
        print("失敗")
    }
}
```

・使えるかどうかを判定したら`UIImagePickerController`のインスタンス作成、ソースの指定、関連付け、表示を行う

```
@IBAction func tapCameraBtn(sender: AnyObject) {
	let sourceType: UIImagePickerControllerSourceType = .Camera
	if UIImagePickerController.isSourceTypeAvailable(.Camera){
        print("成功")
        
        //インスタンスの作成
        let cameraPicker = UIImagePickerController()
        //ソースの指定
        cameraPicker.sourceType = sourceType
        //関連付け
        cameraPicker.delegate = self
        //表示
        self.presentViewController(cameraPicker, animated: true, completion: nil)
        
    }else{
        print("失敗")
    }
}
```

・この時点でこれを実行すればカメラ画面にアクセスしてくれる。

・ただし戻ってくることができない。なのでその帰り道も作ってあげる。`didFinishPickingMediaWithInfo `で

・帰ってくる時に、画像を持ってきて表示したい場合は前もってoutlet形式でUIImageViewを登録しておくこと（名前を今回はcameraViewとした）

```swift
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
        if let pickedImage = info[UIImagePickerControllerOriginalImage] as? UIImage{
        	　//cameraViewは登録しておいたimageView
            cameraView.contentMode = .ScaleAspectFit
            cameraView.image = pickedImage
            
            picker.dismissViewControllerAnimated(true, completion: nil)
        }else{
        print("とれませんでした")
    }
```

・この関数は上のアクション関数の下あたりに書いておけば関連性がわかりやすいかもしれない。

・アルバムにアクセスする場合も上のCameraをPhotoLibraryに代えればいいだけである

##UIImagePickerView関係ないけど画像を保存する方法

・これも前もって専用のボタンを作っておいてアクションのきっかけとする

```
@IBAction func tapSaveBtn(sender: AnyObject) {
	//持ってきた画像にアクセス
    let image: UIImage? = cameraView.image
    //ここがちょっと個人的に特殊な書き方。#selectorの指定の仕方がややこしい
    if let image = image{
        UIImageWriteToSavedPhotosAlbum(image, self, #selector(MainViewController.image(_:didFinishSavingWithError:contextInfo:)), nil)
    }else{
        print("error")
    }
}

//対応するコールバック関数
func image(image: UIImage, didFinishSavingWithError error: NSError!, contextInfo: UnsafeMutablePointer<Void>) {
    if error != nil {
        print("失敗")
    }
    else{
        print("成功")
    }
}
```

・おしまい