diff --git a/README.md b/README.md index 52d56c3..b5dd4a4 100755 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ If you want Swift 2.0 syntax use: ```ruby use_frameworks! -pod 'CameraManager', '~> 2.0’ +pod 'CameraManager', '~> 3.0’ ``` If you want Swift 1.2 syntax use: @@ -39,7 +39,7 @@ Add the following line to your Cartfile: If you want Swift 2.0 syntax use: ``` -github "imaginary-cloud/CameraManager" >= 2.0 +github "imaginary-cloud/CameraManager" >= 3.0 ``` If you want Swift 1.2 syntax use: @@ -53,60 +53,61 @@ And run `carthage update` to build the dynamic framework. ## How to use To use it you just add the preview layer to your desired view, you'll get back the state of the camera if it's unavailable, ready or the user denied assess to it. ```swift -CameraManager.sharedInstance.addPreviewLayerToView(self.cameraView) +let cameraManager +cameraManager.addPreviewLayerToView(self.cameraView) ``` You can set input device to front or back camera: ```swift -CameraManager.sharedInstance.cameraDevice = .Front -CameraManager.sharedInstance.cameraDevice = .Back +cameraManager.cameraDevice = .Front +cameraManager.cameraDevice = .Back ``` You can set output format to Image, video or video with audio: ```swift -CameraManager.sharedInstance.cameraOutputMode = .StillImage -CameraManager.sharedInstance.cameraOutputMode = .VideoWithMic -CameraManager.sharedInstance.cameraOutputMode = .VideoOnly +cameraManager.cameraOutputMode = .StillImage +cameraManager.cameraOutputMode = .VideoWithMic +cameraManager.cameraOutputMode = .VideoOnly ``` You can set the quality: ```swift -CameraManager.sharedInstance.cameraOutputQuality = .Low -CameraManager.sharedInstance.cameraOutputQuality = .Medium -CameraManager.sharedInstance.cameraOutputQuality = .High +cameraManager.cameraOutputQuality = .Low +cameraManager.cameraOutputQuality = .Medium +cameraManager.cameraOutputQuality = .High ``` And flash mode (it will also set corresponding torch mode for video shoot): ```swift -CameraManager.sharedInstance.flashMode = .Off -CameraManager.sharedInstance.flashMode = .On -CameraManager.sharedInstance.flashMode = .Auto +cameraManager.flashMode = .Off +cameraManager.flashMode = .On +cameraManager.flashMode = .Auto ``` To check if the device supports flash call: ```swift -CameraManager.sharedInstance.hasFlash +cameraManager.hasFlash ``` To change flash mode to the next available one you can use this handy function which will also return current value for you to update the UI accordingly: ```swift -CameraManager.sharedInstance.changeFlashMode() +cameraManager.changeFlashMode() ``` You can specify if you want to save the files to phone library: ```swift -CameraManager.sharedInstance.writeFilesToPhoneLibrary = true +cameraManager.writeFilesToPhoneLibrary = true ``` You can specify if you want the user to be asked about camera permissions automatically when you first try to use the camera or manually: ```swift -CameraManager.sharedInstance.showAccessPermissionPopupAutomatically = false +cameraManager.showAccessPermissionPopupAutomatically = false ``` You can even setUp your custom block to handle error messages: It can be customised to be presented on the Window root view controller, for example. ```swift -CameraManager.sharedInstance.showErrorBlock = { (erTitle: String, erMessage: String) -> Void in +cameraManager.showErrorBlock = { (erTitle: String, erMessage: String) -> Void in var alertController = UIAlertController(title: erTitle, message: erMessage, preferredStyle: .Alert) alertController.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler: { (alertAction) -> Void in })) @@ -124,22 +125,22 @@ CameraManager.sharedInstance.showErrorBlock = { (erTitle: String, erMessage: Str To shoot image all you need to do is call: ```swift -CameraManager.sharedInstance.capturePictureWithCompletition({ (image, error) -> Void in +cameraManager.capturePictureWithCompletition({ (image, error) -> Void in self.myImage = image }) ``` To record video you do: ```swift -CameraManager.sharedInstance.startRecordingVideo() -CameraManager.sharedInstance.stopRecordingVideo({ (videoURL, error) -> Void in +cameraManager.startRecordingVideo() +cameraManager.stopRecordingVideo({ (videoURL, error) -> Void in NSFileManager.defaultManager().copyItemAtURL(videoURL, toURL: self.myVideoURL, error: &error) }) ``` ## Support -Supports iOS 8 and above. Xcode 6.3 is required to build the latest code written in Swift 1.2. +Supports iOS 8 and above. Xcode 7.0 is required to build the latest code written in Swift 2.0. ## License diff --git a/camera/CameraManager.swift b/camera/CameraManager.swift index a04781a..22d1037 100644 --- a/camera/CameraManager.swift +++ b/camera/CameraManager.swift @@ -10,8 +10,6 @@ import UIKit import AVFoundation import AssetsLibrary -private let _singletonSharedInstance = CameraManager() - public enum CameraState { case Ready, AccessDenied, NoDeviceFound, NotDetermined } @@ -36,11 +34,6 @@ public enum CameraOutputQuality: Int { public class CameraManager: NSObject, AVCaptureFileOutputRecordingDelegate { // MARK: - Public properties - - /// CameraManager singleton instance to use the camera. - public class var sharedInstance: CameraManager { - return _singletonSharedInstance - } /// Capture session to customize camera settings. public var captureSession: AVCaptureSession? @@ -131,10 +124,11 @@ public class CameraManager: NSObject, AVCaptureFileOutputRecordingDelegate { /// Property to check video recording file size when in progress public var recordedFileSize : Int64 { return movieOutput?.recordedFileSize ?? 0 } + // MARK: - Private properties private weak var embedingView: UIView? - private var videoCompletition: ((videoURL: NSURL, error: NSError?) -> Void)? + private var videoCompletition: ((videoURL: NSURL?, error: NSError?) -> Void)? private var sessionQueue: dispatch_queue_t = dispatch_queue_create("CameraSessionQueue", DISPATCH_QUEUE_SERIAL) @@ -334,7 +328,7 @@ public class CameraManager: NSObject, AVCaptureFileOutputRecordingDelegate { /** Stop recording a video. Save it to the cameraRoll and give back the url. */ - public func stopRecordingVideo(completition:(videoURL: NSURL, error: NSError?) -> Void) { + public func stopRecordingVideo(completition:(videoURL: NSURL?, error: NSError?) -> Void) { if let runningMovieOutput = movieOutput { if runningMovieOutput.recording { videoCompletition = completition @@ -392,6 +386,7 @@ public class CameraManager: NSObject, AVCaptureFileOutputRecordingDelegate { validLibrary.writeVideoAtPathToSavedPhotosAlbum(outputFileURL, completionBlock: { (assetURL: NSURL?, error: NSError?) -> Void in if (error != nil) { self._show(NSLocalizedString("Unable to save video to the iPhone.", comment:""), message: error!.localizedDescription) + self._executeVideoCompletitionWithURL(nil, error: error) } else { if let validAssetURL = assetURL { self._executeVideoCompletitionWithURL(validAssetURL, error: error) @@ -428,7 +423,7 @@ public class CameraManager: NSObject, AVCaptureFileOutputRecordingDelegate { captureSession?.commitConfiguration() } - private func _executeVideoCompletitionWithURL(url: NSURL, error: NSError?) { + private func _executeVideoCompletitionWithURL(url: NSURL?, error: NSError?) { if let validCompletition = videoCompletition { validCompletition(videoURL: url, error: error) videoCompletition = nil diff --git a/camera/ViewController.swift b/camera/ViewController.swift index a12006c..13aaa0f 100644 --- a/camera/ViewController.swift +++ b/camera/ViewController.swift @@ -12,7 +12,7 @@ class ViewController: UIViewController { // MARK: - Constants - let cameraManager = CameraManager.sharedInstance + let cameraManager = CameraManager() // MARK: - @IBOutlets @@ -30,22 +30,22 @@ class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() - self.cameraManager.showAccessPermissionPopupAutomatically = false + cameraManager.showAccessPermissionPopupAutomatically = false - self.askForPermissionsButton.hidden = true - self.askForPermissionsLabel.hidden = true + askForPermissionsButton.hidden = true + askForPermissionsLabel.hidden = true - let currentCameraState = self.cameraManager.currentCameraStatus() + let currentCameraState = cameraManager.currentCameraStatus() if currentCameraState == .NotDetermined { - self.askForPermissionsButton.hidden = false - self.askForPermissionsLabel.hidden = false + askForPermissionsButton.hidden = false + askForPermissionsLabel.hidden = false } else if (currentCameraState == .Ready) { - self.addCameraToView() + addCameraToView() } - if !self.cameraManager.hasFlash { - self.flashModeButton.enabled = false - self.flashModeButton.setTitle("No flash", forState: UIControlState.Normal) + if !cameraManager.hasFlash { + flashModeButton.enabled = false + flashModeButton.setTitle("No flash", forState: UIControlState.Normal) } } @@ -53,13 +53,13 @@ class ViewController: UIViewController { override func viewWillAppear(animated: Bool) { super.viewWillAppear(animated) - self.navigationController?.navigationBar.hidden = true - self.cameraManager.resumeCaptureSession() + navigationController?.navigationBar.hidden = true + cameraManager.resumeCaptureSession() } override func viewWillDisappear(animated: Bool) { super.viewWillDisappear(animated) - self.cameraManager.stopCaptureSession() + cameraManager.stopCaptureSession() } @@ -67,8 +67,8 @@ class ViewController: UIViewController { private func addCameraToView() { - self.cameraManager.addPreviewLayerToView(self.cameraView, newCameraOutputMode: CameraOutputMode.VideoWithMic) - CameraManager.sharedInstance.showErrorBlock = { (erTitle: String, erMessage: String) -> Void in + cameraManager.addPreviewLayerToView(cameraView, newCameraOutputMode: CameraOutputMode.VideoWithMic) + cameraManager.showErrorBlock = { (erTitle: String, erMessage: String) -> Void in // var alertController = UIAlertController(title: erTitle, message: erMessage, preferredStyle: .Alert) // alertController.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler: { (alertAction) -> Void in @@ -89,7 +89,7 @@ class ViewController: UIViewController { @IBAction func changeFlashMode(sender: UIButton) { - switch (self.cameraManager.changeFlashMode()) { + switch (cameraManager.changeFlashMode()) { case .Off: sender.setTitle("Flash Off", forState: UIControlState.Normal) case .On: @@ -101,9 +101,9 @@ class ViewController: UIViewController { @IBAction func recordButtonTapped(sender: UIButton) { - switch (self.cameraManager.cameraOutputMode) { + switch (cameraManager.cameraOutputMode) { case .StillImage: - self.cameraManager.capturePictureWithCompletition({ (image, error) -> Void in + cameraManager.capturePictureWithCompletition({ (image, error) -> Void in let vc: ImageViewController? = self.storyboard?.instantiateViewControllerWithIdentifier("ImageVC") as? ImageViewController if let validVC: ImageViewController = vc { if let capturedImage = image { @@ -117,9 +117,9 @@ class ViewController: UIViewController { sender.setTitle(" ", forState: UIControlState.Selected) sender.backgroundColor = sender.selected ? UIColor.redColor() : UIColor.greenColor() if sender.selected { - self.cameraManager.startRecordingVideo() + cameraManager.startRecordingVideo() } else { - self.cameraManager.stopRecordingVideo({ (videoURL, error) -> Void in + cameraManager.stopRecordingVideo({ (videoURL, error) -> Void in if let errorOccured = error { self.cameraManager.showErrorBlock(erTitle: "Error occurred", erMessage: errorOccured.localizedDescription) } @@ -130,11 +130,11 @@ class ViewController: UIViewController { @IBAction func outputModeButtonTapped(sender: UIButton) { - self.cameraManager.cameraOutputMode = self.cameraManager.cameraOutputMode == CameraOutputMode.VideoWithMic ? CameraOutputMode.StillImage : CameraOutputMode.VideoWithMic - switch (self.cameraManager.cameraOutputMode) { + cameraManager.cameraOutputMode = cameraManager.cameraOutputMode == CameraOutputMode.VideoWithMic ? CameraOutputMode.StillImage : CameraOutputMode.VideoWithMic + switch (cameraManager.cameraOutputMode) { case .StillImage: - self.cameraButton.selected = false - self.cameraButton.backgroundColor = UIColor.greenColor() + cameraButton.selected = false + cameraButton.backgroundColor = UIColor.greenColor() sender.setTitle("Image", forState: UIControlState.Normal) case .VideoWithMic, .VideoOnly: sender.setTitle("Video", forState: UIControlState.Normal) @@ -143,8 +143,8 @@ class ViewController: UIViewController { @IBAction func changeCameraDevice(sender: UIButton) { - self.cameraManager.cameraDevice = self.cameraManager.cameraDevice == CameraDevice.Front ? CameraDevice.Back : CameraDevice.Front - switch (self.cameraManager.cameraDevice) { + cameraManager.cameraDevice = cameraManager.cameraDevice == CameraDevice.Front ? CameraDevice.Back : CameraDevice.Front + switch (cameraManager.cameraDevice) { case .Front: sender.setTitle("Front", forState: UIControlState.Normal) case .Back: @@ -154,7 +154,7 @@ class ViewController: UIViewController { @IBAction func askForCameraPermissions(sender: UIButton) { - self.cameraManager.askUserForCameraPermissions({ permissionGranted in + cameraManager.askUserForCameraPermissions({ permissionGranted in self.askForPermissionsButton.hidden = true self.askForPermissionsLabel.hidden = true self.askForPermissionsButton.alpha = 0 @@ -167,7 +167,7 @@ class ViewController: UIViewController { @IBAction func changeCameraQuality(sender: UIButton) { - switch (self.cameraManager.changeQualityMode()) { + switch (cameraManager.changeQualityMode()) { case .High: sender.setTitle("High", forState: UIControlState.Normal) case .Low: