17
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

AVFoundationで背面カメラと前面カメラの切り替えをする

Last updated at Posted at 2016-11-18

環境

  • Xcode 8.1
  • えるたそ (OS X El Capitan 10.11.6)
  • Swift 3.0.1
  • iOS 10.1 (iPhoneSE)

画面構成

正方形の previewView (UIView)が配置されていて、
changeUseCamera: アクションボタンと pushShutter: アクションボタンが設置されています。

サンプルソースコード

ViewController.swift
import UIKit
import AVFoundation

class ViewController: UIViewController {

	@IBOutlet weak var previewView: UIView!
	
	var isBackCamera: Bool = true
	var captureSession: AVCaptureSession!
	var cameraDevices: AVCaptureDevice!
	var imageOutput: AVCaptureStillImageOutput!
	
	// MARK: - Life Cycle
	override func viewWillAppear(_ animated: Bool) {
		super.viewWillAppear(animated)
		self.setupCamera(isBack: self.isBackCamera)
	}

	// MARK: - Private Method
	fileprivate func setupCamera(isBack: Bool) {
		guard let devices = AVCaptureDevice.devices() else {
			return
		}
		for device in devices {
			// isBack == True  -> Back Camera
			// iSBack == False -> Front Camera
			let devicePosition: AVCaptureDevicePosition = isBack ? .back : .front
			if (device as AnyObject).position == devicePosition {
				self.cameraDevices = device as! AVCaptureDevice
			}
		}

		let videoInput: AVCaptureInput!
		do {
			videoInput = try AVCaptureDeviceInput.init(device: self.cameraDevices)
		} catch {
			videoInput = nil
		}

		self.captureSession = AVCaptureSession()
		self.captureSession.addInput(videoInput)

		self.imageOutput = AVCaptureStillImageOutput()
		self.captureSession.addOutput(self.imageOutput)

		let captureVideoLayer = AVCaptureVideoPreviewLayer.init(session: self.captureSession)
		let layerRect = CGRect(x: self.previewView.frame.origin.x,
						       y: 0,
						       width: UIScreen.main.bounds.size.width,
						       height: UIScreen.main.bounds.size.width)

		captureVideoLayer?.frame = layerRect
		captureVideoLayer?.videoGravity = AVLayerVideoGravityResizeAspectFill

		guard let videoLayer = captureVideoLayer else {
			return
		}
		self.previewView.layer.addSublayer(videoLayer)

		// 開始
		self.captureSession.startRunning()
	}
	
	// MARK: - IBAction
	
	// Change Camera
	@IBAction func changeUseCamera(_ sender: Any) {
		self.isBackCamera = !self.isBackCamera
		setupCamera(isBack: self.isBackCamera)
	}

	// Save taken photo
	@IBAction func pushShutter(_ sender: Any) {
		let captureVideoConnection = imageOutput.connection(withMediaType: AVMediaTypeVideo)

		self.imageOutput.captureStillImageAsynchronously(from: captureVideoConnection) { [weak self] (imageDataBuffer, error) -> Void in

			let capturedImageData: Data = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(imageDataBuffer) as Data

			guard let image = UIImage(data: capturedImageData),
					let wself = self else {
				return
			}

			UIImageWriteToSavedPhotosAlbum(image, wself, nil, nil)
		}
	}
}

補足

このままだと、一度アプリから離脱をしてしまうとカメラのセッションが切れてしまうので AppDelegate.swiftapplicationDidBecomeActive: 等のメソッドを使って通知してセッションを再始動しないとダメなようです。

17
10
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
17
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?