CameraManager/camera/CameraManager.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()
})
}
}