LoginSignup
17
10

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