iPadとPlaygroundsで学ぶ:内蔵カメラで写真を撮る【UIImagePickerController編】
内蔵カメラでの写真撮影に挑戦します。
カメラの機能を使う場合、以下の2つの方法があるようです。
- UIImagePickerControllerでシステムカメラを利用する(お手軽,細かい制御はできない)
- AVFoundationでカメラの機能を直接使う(色々自分で実装する必要がある,細かい制御ができる)
今回はUIImagePickerControllerを使ってみます。 developer.apple.com
UIImagePickerControllerでカメラを起動
UIImagePickerControllerを使うと以下の手順でカメラを起動することができます。
- UIImagePickerControllerのインスタンスを生成する
- 生成したインスタンスのsourceTypeにUIImagePickerController.SourceType.cameraを設定する
- プロトコルを登録する
- presentで生成したインスタンスへ画面遷移する
非常に簡単ですね。3.については次で説明します。
appleのサイトにはsourceTypeとmediaTypeが対応しているものかどうか確認するように書いてありますが今回は割愛します。
撮影結果を受け取る
UIImagePickerControllerの役割は画像データを準備してくれるところまでです。画像データを受け取るためにはプロトコルを使います。
プロトコルは他の言語で言うところのインターフェースクラスみたいなものです。 プロトコルを継承したクラスで必要な関数を実装し、そのクラスのインスタンスをコントローラーに登録することでイベントが発生した時に通知してもらうことが出来ます。
UIImagePickerControllerの通知は次のプロトコルを継承して受け取ります。
// プロトコル UIImagePickerControllerDelegate // 画像データが準備できたことを通知してもらう関数 UIImagePickerControllerDelegate. imagePickerController // キャンセルされたことを通知してもらう関数 UIImagePickerControllerDelegate. imagePickerControllerDidCancel
上記の関数は通知に対して何か処理したいものだけ実装すれば良いです。今回はimagePickerControllerのみ実装します。
画像データはimagePickerController関数の第2引数(info)に格納されて渡されます。 infoは連想配列でいくつかの情報を保持しており、撮影した画像データはキーUIImagePickerController.InfoKey.originalImageを指定して取り出せます。
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) { // 取り出してからUIImageにキャストする let image = info[UIImagePickerController.InfoKey.originalImage] as? UIImage }
またUIImagePickerControllerにプロトコルを登録する場合は画面遷移に関する下記プロトコルも継承する必要があります。こちらについても処理を追加したい関数のみ実装すれば良いです。
UINavigationControllerDelegate
アプリの仕様
ビューにボタンを配置しボタンが押されたときにシステムカメラを起動します。 画像を撮影しキャンセルされなかった場合には画面をアルバムに保存します。
コード
以下コードです。
import UIKit class ViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate { var imagePicker: UIImagePickerController? var mainView: UIView? var button: UIButton? override func viewDidLoad() { createElements() setAnchorConstraint() } func createElements() { self.imagePicker = UIImagePickerController() self.mainView = UIView() self.button = UIButton() guard let imagePicker = self.imagePicker, let mainView = self.mainView, let button = self.button else { return } button.backgroundColor = UIColor.magenta button.addTarget(self, action:#selector(self.buttonEvent(_:)), for: UIButton.Event.touchUpInside) mainView.addSubview(button) self.view = mainView } func setAnchorConstraint() { guard let mainView = self.view, let button = self.button else { return } button.translatesAutoresizingMaskIntoConstraints = false button.centerXAnchor.constraint(equalTo:mainView.centerXAnchor).isActive = true button.bottomAnchor.constraint(equalTo:mainView.bottomAnchor, constant: -100).isActive = true button.widthAnchor.constraint(equalToConstant:60).isActive = true button.heightAnchor.constraint(equalToConstant:30).isActive = true } func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) { // 撮影結果から画像データを取り出す if let image = info[UIImagePickerController.InfoKey.originalImage] as? UIImage { // アルバムへ保存 UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil) } // 遷移元へ戻る picker.dismiss(animated:true, completion:nil) } @objc func buttonEvent(_ sender: UIButton) { guard let imagePicker = self.imagePicker else { return } // UIImagePickerControllerの設定 imagePicker.sourceType = UIImagePickerController.SourceType.camera // protocolを設定 imagePicker.delegate = self // 画面遷移 present(imagePicker, animated:true, completion:nil) } } import PlaygroundSupport PlaygroundPage.current.liveView = ViewController()
アルバムに保存する関数は実行結果を受け取るイベントを指定できるようですが今回は省略します。
実機で実行する場合
iPad + Playgroundsでは特に問題なく実行できましたが、実機でこのプログラムを動かす場合にはユーザー許可が必要です。 ユーザー許可の設定方法については実機で動かすときにまとめたいと思います。