160 lines
5.5 KiB
Swift
160 lines
5.5 KiB
Swift
//
|
|
// CameraManager.swift
|
|
// camera
|
|
//
|
|
// Created by Natalia Terlecka on 10/10/14.
|
|
// Copyright (c) 2014 imaginaryCloud. All rights reserved.
|
|
//
|
|
|
|
import UIKit
|
|
import AVFoundation
|
|
|
|
private let _singletonSharedInstance = CameraManager()
|
|
|
|
class CameraManager: NSObject {
|
|
|
|
var captureSession: AVCaptureSession?
|
|
|
|
private var sessionQueue: dispatch_queue_t = dispatch_queue_create("CameraSessionQueue", DISPATCH_QUEUE_SERIAL)
|
|
private var frontCamera: AVCaptureInput?
|
|
private var rearCamera: AVCaptureInput?
|
|
private var stillImageOutput: AVCaptureStillImageOutput?
|
|
private var previewLayer: AVCaptureVideoPreviewLayer?
|
|
private var cameraIsSetup = false
|
|
|
|
class var sharedInstance: CameraManager {
|
|
return _singletonSharedInstance
|
|
}
|
|
|
|
func addPreeviewLayerToView(view: UIView)
|
|
{
|
|
if self.cameraIsSetup {
|
|
self._addPreeviewLayerToView(view)
|
|
} else {
|
|
self._setupCamera({ Void -> Void in
|
|
self._addPreeviewLayerToView(view)
|
|
})
|
|
}
|
|
}
|
|
|
|
func capturePictureWithCompletition(imageCompletition: UIImage -> Void)
|
|
{
|
|
dispatch_async(self.sessionQueue, {
|
|
if let validStillImageOutput = self.stillImageOutput? {
|
|
validStillImageOutput.captureStillImageAsynchronouslyFromConnection(validStillImageOutput.connectionWithMediaType(AVMediaTypeVideo), completionHandler: { [weak self] (sample: CMSampleBuffer!, error: NSError!) -> Void in
|
|
if (error? != nil) {
|
|
dispatch_async(dispatch_get_main_queue(), {
|
|
if let weakSelf = self {
|
|
weakSelf._show("error", message: error.localizedDescription)
|
|
}
|
|
})
|
|
} else {
|
|
let imageData = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(sample)
|
|
imageCompletition(UIImage(data: imageData))
|
|
}
|
|
})
|
|
}
|
|
})
|
|
}
|
|
|
|
func startFollowingDeviceOrientation()
|
|
{
|
|
NSNotificationCenter.defaultCenter().addObserver(self, selector: "orientationChanged", name: UIDeviceOrientationDidChangeNotification, object: nil)
|
|
}
|
|
|
|
func orientationChanged()
|
|
{
|
|
|
|
}
|
|
|
|
private func _setupCamera(completition: Void -> Void)
|
|
{
|
|
self._checkIfCameraIsAvailable()
|
|
|
|
self.captureSession = AVCaptureSession()
|
|
self.captureSession?.sessionPreset = AVCaptureSessionPresetPhoto
|
|
|
|
dispatch_async(sessionQueue, {
|
|
if let validCaptureSession = self.captureSession? {
|
|
validCaptureSession.beginConfiguration()
|
|
self._addVideoInput()
|
|
self._addStillImageOutput()
|
|
self._setupPreviewLayer()
|
|
validCaptureSession.commitConfiguration()
|
|
validCaptureSession.startRunning()
|
|
completition()
|
|
self.cameraIsSetup = true
|
|
}
|
|
})
|
|
}
|
|
|
|
private func _addPreeviewLayerToView(view: UIView)
|
|
{
|
|
dispatch_async(dispatch_get_main_queue(), { () -> Void in
|
|
self.previewLayer?.frame = view.layer.bounds
|
|
view.clipsToBounds = true
|
|
view.layer.addSublayer(self.previewLayer)
|
|
})
|
|
}
|
|
|
|
private func _checkIfCameraIsAvailable()
|
|
{
|
|
AVCaptureDevice.requestAccessForMediaType(AVMediaTypeVideo, completionHandler: { (cameraAvailable) -> Void in
|
|
if !cameraAvailable {
|
|
self._show("Camera unavailable", message: "The app does not have access to camera")
|
|
}
|
|
})
|
|
}
|
|
|
|
private func _addVideoInput()
|
|
{
|
|
var error: NSError?
|
|
|
|
var videoFrontDevice: AVCaptureDevice?
|
|
var videoBackDevice: AVCaptureDevice?
|
|
for device: AnyObject in AVCaptureDevice.devicesWithMediaType(AVMediaTypeVideo) {
|
|
if device.position == AVCaptureDevicePosition.Back {
|
|
videoBackDevice = device as? AVCaptureDevice
|
|
} else if device.position == AVCaptureDevicePosition.Front {
|
|
videoFrontDevice = device as? AVCaptureDevice
|
|
}
|
|
}
|
|
if let validVideoFrontDevice = videoFrontDevice? {
|
|
self.frontCamera = AVCaptureDeviceInput.deviceInputWithDevice(validVideoFrontDevice, error: &error) as AVCaptureDeviceInput
|
|
}
|
|
if let validVideoBackDevice = videoBackDevice? {
|
|
self.rearCamera = AVCaptureDeviceInput.deviceInputWithDevice(validVideoBackDevice, error: &error) as AVCaptureDeviceInput
|
|
if !(error != nil) {
|
|
if let validBackDevice = self.rearCamera? {
|
|
self.captureSession?.addInput(validBackDevice)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private func _addStillImageOutput()
|
|
{
|
|
self.stillImageOutput = AVCaptureStillImageOutput()
|
|
if let validStillImageOutput = self.stillImageOutput? {
|
|
self.captureSession?.addOutput(self.stillImageOutput)
|
|
}
|
|
}
|
|
|
|
private func _setupPreviewLayer()
|
|
{
|
|
self.previewLayer = AVCaptureVideoPreviewLayer(session: self.captureSession)
|
|
self.previewLayer?.videoGravity = AVLayerVideoGravityResizeAspectFill
|
|
}
|
|
|
|
private func _show (title: String, message: String)
|
|
{
|
|
dispatch_async(dispatch_get_main_queue(), { () -> Void in
|
|
UIAlertView(
|
|
title: title,
|
|
message: message,
|
|
delegate: self,
|
|
cancelButtonTitle: "OK").show()
|
|
})
|
|
}
|
|
}
|