// // CameraView.swift // CapFinder // // Created by User on 07.02.18. // Copyright © 2018 User. All rights reserved. // import UIKit import AVFoundation class CameraView: UIView { // MARK: UIView overrides /** Override for AVCapture */ override class var layerClass: AnyClass { return AVCaptureVideoPreviewLayer.self } // MARK: Enums private enum SessionSetupResult { case success case notAuthorized case configurationFailed } // MARK: Variables var delegate: PhotoCaptureHandlerDelegate? { get { return photoCaptureProcessor.delegate } set { photoCaptureProcessor.delegate = newValue } } private let session = AVCaptureSession() private var isSessionRunning = false /// Communicate with the session and other session objects on this queue. private let sessionQueue = DispatchQueue(label: "session queue") private var setupResult: SessionSetupResult = .success var videoDeviceInput: AVCaptureDeviceInput! private let photoOutput = AVCapturePhotoOutput() private let photoCaptureProcessor = PhotoCaptureHandler() var videoPreviewLayer: AVCaptureVideoPreviewLayer { return layer as! AVCaptureVideoPreviewLayer } // MARK: Life cycle func configure() { videoPreviewLayer.session = session checkPermission() // Setup the capture session. sessionQueue.async { self.configureSession() } } func launch(completionHandler: @escaping (Bool, String?) -> ()) { sessionQueue.async { switch self.setupResult { case .success: // Only setup observers and start the session running if setup succeeded. self.session.startRunning() self.isSessionRunning = self.session.isRunning case .notAuthorized: DispatchQueue.main.async { completionHandler(false, "No camera access") } case .configurationFailed: DispatchQueue.main.async { completionHandler(false, "Camera error") } } } } func complete() { sessionQueue.async { if self.setupResult == .success { self.session.stopRunning() self.isSessionRunning = self.session.isRunning } } } // MARK: Photo Capture func capture() { sessionQueue.async { self.photoOutput.capturePhoto( with: self.photoCaptureProcessor.photoSettings, delegate: self.photoCaptureProcessor) } } // MARK: Camera permissions private func checkPermission() { switch AVCaptureDevice.authorizationStatus(for: .video) { case .authorized: break case .notDetermined: sessionQueue.suspend() AVCaptureDevice.requestAccess(for: .video, completionHandler: { granted in if !granted { self.setupResult = .notAuthorized } self.sessionQueue.resume() }) default: // The user has previously denied access. setupResult = .notAuthorized } } // Call this on the session queue. private func configureSession() { if setupResult != .success { return } session.beginConfiguration() /* We do not create an AVCaptureMovieFileOutput when setting up the session because the AVCaptureMovieFileOutput does not support movie recording with AVCaptureSession.Preset.Photo. */ session.sessionPreset = .photo // Add video input. do { guard let backCameraDevice = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: .back) else { print("No camera on device") setupResult = .configurationFailed session.commitConfiguration() return } let videoDeviceInput = try AVCaptureDeviceInput(device: backCameraDevice) if session.canAddInput(videoDeviceInput) { session.addInput(videoDeviceInput) self.videoDeviceInput = videoDeviceInput DispatchQueue.main.async { self.videoPreviewLayer.connection?.videoOrientation = .portrait } } else { print("Could not add video device input to the session") setupResult = .configurationFailed session.commitConfiguration() return } } catch { print("Could not create video device input: \(error)") setupResult = .configurationFailed session.commitConfiguration() return } // Add photo output. if session.canAddOutput(photoOutput) { session.addOutput(photoOutput) photoOutput.isHighResolutionCaptureEnabled = true photoOutput.isDepthDataDeliveryEnabled = false photoOutput.isDualCameraDualPhotoDeliveryEnabled = false photoOutput.isLivePhotoCaptureEnabled = false } else { print("Could not add photo output to the session") setupResult = .configurationFailed session.commitConfiguration() return } session.commitConfiguration() } }