I know this is possible, saw this in some apps (iGotYa is I believe the most famous). I know how to set up everything for taking photos, saving it and everything. But how ca
This is very simple, just use the AVFoundation reference guide:
https://developer.apple.com/library/ios/#documentation/AudioVideo/Conceptual/AVFoundationPG/Articles/04_MediaCapture.html
If you don't want the user to see the preview input you can just skip the set preview layer part of the code.
Edit: To be more detailed.
1)You set your capture configuration using the AVFoundation.
2)You SKIP the part where the video preview layer is set.
3)You call the captureStillImageAsynchronouslyFromConnection:completionHandler: method whenever you want the picture to be taken.
Note: If you want the flash to not be heard and such then you might be violating the user rights in some countries (japan for example). One workaround I know of to do so is by capturing a frame of a video (does not trigger flash).
You can also do it without AVFoundation and it is in my opinion an easier way to implement it using only the UIImagePickerController. There are 3 conditions:
Below is a simple example that you woul typically trigger after a button push
- (IBAction)takePhoto:(id)sender
{
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
picker.sourceType = UIImagePickerControllerSourceTypeCamera;
picker.cameraDevice = UIImagePickerControllerCameraDeviceFront;
picker.showsCameraControls = NO;
[self presentViewController:picker animated:YES
completion:^ {
[picker takePicture];
}];
}
Swift 5.2
For reference https://gist.github.com/hadanischal/33054429b18287c12ed4f4b8d45a1701
Info.plist
<key>NSCameraUsageDescription</key>
<string>Access camera</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>Access PhotoLibrary</string>
AVFoundationHelper
import AVFoundation
enum CameraStatus {
case notDetermined
case restricted
case denied
case authorized
}
protocol AVFoundationHelperProtocol: AnyObject {
// MARK: - Check and Respond to Camera Authorization Status
var authorizationStatus: CameraStatus { get }
// MARK: - Request Camera Permission
func requestAccess(completionHandler handler: @escaping (Bool) -> Void)
}
final class AVFoundationHelper: AVFoundationHelperProtocol {
// MARK: - Check and Respond to Camera Authorization Status
var authorizationStatus: CameraStatus {
let cameraAuthorizationStatus = AVCaptureDevice.authorizationStatus(for: .video)
switch cameraAuthorizationStatus {
case .notDetermined:
return CameraStatus.notDetermined
case .authorized:
return CameraStatus.authorized
case .restricted:
return CameraStatus.restricted
case .denied:
return CameraStatus.denied
@unknown default:
return CameraStatus.notDetermined
}
}
// MARK: - Request Camera Permission
func requestAccess(completionHandler handler: @escaping (Bool) -> Void) {
AVCaptureDevice.requestAccess(for: .video, completionHandler: { accessGranted in
handler(accessGranted)
})
}
}
ViewController
import UIKit
final class ViewController: UIViewController {
@IBOutlet var cameraAccessButton: UIButton!
@IBOutlet var photoImageView: UIImageView!
private var model: AVFoundationHelperProtocol = AVFoundationHelper()
override func viewDidLoad() {
super.viewDidLoad()
}
@IBAction func cameraButtonPressed(_: Any) {
let status = model.authorizationStatus
switch status {
case .notDetermined:
model.requestAccess { hasAccess in
if hasAccess {
DispatchQueue.main.async {
self.showCameraReader()
}
} else {
self.alertCameraAccessNeeded()
}
}
case .restricted, .denied:
alertCameraAccessNeeded()
case .authorized:
showCameraReader()
}
}
private func alertCameraAccessNeeded() {
let appName = "This app Name"
let alert = UIAlertController(title: "This feature requires Camera Access",
message: "In iPhone settings, tap \(appName) and turn on Camera access",
preferredStyle: UIAlertController.Style.alert)
let actionSettings = UIAlertAction(title: "Settings", style: .default, handler: { _ -> Void in
guard let settingsAppURL = URL(string: UIApplication.openSettingsURLString) else { return }
UIApplication.shared.open(settingsAppURL)
})
let actionCancel = UIAlertAction(title: "Cancel", style: .destructive, handler: { _ -> Void in
})
alert.addAction(actionSettings)
alert.addAction(actionCancel)
present(alert, animated: true, completion: nil)
}
}
extension ViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
private func showCameraReader() {
if UIImagePickerController.isSourceTypeAvailable(.camera) {
let imagePicker = UIImagePickerController()
imagePicker.sourceType = .camera
imagePicker.allowsEditing = true
imagePicker.delegate = self
present(imagePicker, animated: true)
} else if UIImagePickerController.isSourceTypeAvailable(.photoLibrary) {
let imagePicker = UIImagePickerController()
imagePicker.sourceType = .photoLibrary
imagePicker.allowsEditing = true
imagePicker.delegate = self
present(imagePicker, animated: true)
} else {
// TODO: Implement proper alert
alertCameraAccessNeeded()
}
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) {
picker.dismiss(animated: true)
guard let image = info[.editedImage] as? UIImage else {
print("No image found")
return
}
photoImageView.image = image
// print out the image size as a test
print(image.size)
}
}
Objective C
In .h file
@interface ABCViewController : UIViewController
@property (strong, nonatomic) IBOutlet UIImageView *imageView;
- (IBAction)takePhoto: (UIButton *)sender;
- (IBAction)selectPhoto:(UIButton *)sender;
@end
In .m file
@interface ABCViewController : UIViewController <UIImagePickerControllerDelegate, UINavigationControllerDelegate>
- (IBAction)takePhoto:(UIButton *)sender {
if (![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
UIAlertView *myAlertView = [[UIAlertView alloc] initWithTitle:@"Error"
message:@"Device has no camera"
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles: nil];
[myAlertView show];
} else {
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
picker.allowsEditing = YES;
picker.sourceType = UIImagePickerControllerSourceTypeCamera;
[self presentViewController:picker animated:YES completion:NULL];
}
}
- (IBAction)selectPhoto:(UIButton *)sender {
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
picker.allowsEditing = YES;
picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
[self presentViewController:picker animated:YES completion:NULL];
}
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
UIImage *chosenImage = info[UIImagePickerControllerEditedImage];
self.imageView.image = chosenImage;
[picker dismissViewControllerAnimated:YES completion:NULL];
}
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
[picker dismissViewControllerAnimated:YES completion:NULL];
}
VLBCameraView is a library that uses AVFoundation to take photo.
A preview is shown in the view, which you can then call the method VLBCameraView#takePicture programmatically to take a photo.
Comes with CocoaPods.
Here is the code for Objective -C Custom Camera. You can add features, buttons according to your wish.
#import "CustomCameraVC.h"
@interface CustomCameraVC () {
BOOL frontCamera;
}
@property (strong,nonatomic) AVCaptureSession *captureSession;
@property (strong,nonatomic) AVCaptureStillImageOutput *stillImageOutput;
@property (strong,nonatomic) AVCaptureVideoPreviewLayer *videoPreviewLayer;
@property (weak, nonatomic) IBOutlet UIView *viewCamera;
@end
@implementation CustomCameraVC
- (void)viewDidLoad {
[super viewDidLoad];
}
-(void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:YES];
frontCamera = NO;
[self showCameraWithFrontCamera:frontCamera];
}
-(void)showCameraWithFrontCamera:(BOOL)flag {
self.captureSession = [[AVCaptureSession alloc]init];
self.captureSession.sessionPreset = AVCaptureSessionPresetPhoto;
AVCaptureDevice *captureDevice;
if(flag) {
captureDevice= [self frontCamera];
}
else {
captureDevice= [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
}
NSError *error = nil;
AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:captureDevice error:&error];
[self.captureSession addInput:input];
self.stillImageOutput = [AVCaptureStillImageOutput new];
self.stillImageOutput.outputSettings = @{AVVideoCodecKey:AVVideoCodecJPEG};
[self.captureSession addOutput:_stillImageOutput];
self.videoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:self.captureSession];
self.videoPreviewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
self.videoPreviewLayer.connection.videoOrientation = AVCaptureVideoOrientationPortrait;
[self.viewCamera.layer addSublayer:self.videoPreviewLayer];
[self.captureSession startRunning];
self.videoPreviewLayer.frame = self.viewCamera.bounds;
}
- (AVCaptureDevice *)frontCamera {
NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
for (AVCaptureDevice *device in devices) {
if ([device position] == AVCaptureDevicePositionFront) {
return device;
}
}
return nil;
}
- (IBAction)btnCaptureImagePressed:(id)sender {
AVCaptureConnection * videoConnection = [_stillImageOutput connectionWithMediaType:AVMediaTypeVideo];
[_stillImageOutput captureStillImageAsynchronouslyFromConnection:videoConnection completionHandler:^(CMSampleBufferRef _Nullable sampleBuffer, NSError * _Nullable error) {
NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:sampleBuffer];
UIImage *image = [[UIImage alloc]initWithData: imageData];
UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil);
}];
}
@end