Scatta una foto su iPhone senza mostrare i controlli

C’è un modo per scattare una foto in codice su iPhone senza passare attraverso i controlli Apple? Ho visto un sacco di app che fanno questo, ma non sono sicuro di quale chiamata API usare.

Sì, ci sono due modi per farlo. Uno, disponibile in iOS 3.0+, consiste nell’utilizzare la class UIImagePickerController , impostare la proprietà showsCameraControls su NO e impostare la proprietà cameraOverlayView sui propri controlli personalizzati. Due, disponibile in iOS 4.0+, è quello di configurare una AVCaptureSession , fornendola con AVCaptureDeviceInput utilizzando il dispositivo della fotocamera appropriato e AVCaptureStillImageOutput . Il primo approccio è molto più semplice e funziona su più versioni iOS, ma il secondo approccio offre un maggiore controllo sulla risoluzione delle foto e sulle opzioni dei file.

EDIT: Come suggerito nei commenti qui sotto, ho ora esplicitamente mostrato come AVCaptureSession deve essere dichiarato e inizializzato. Sembra che alcuni stessero facendo l’inizializzazione sbagliata o dichiarando AVCaptureSession come una variabile locale in un metodo. Questo non funzionerebbe.

Il codice seguente consente di scattare una foto utilizzando AVCaptureSession senza l’input dell’utente:

 // Get all cameras in the application and find the frontal camera. AVCaptureDevice *frontalCamera; NSArray *allCameras = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo]; // Find the frontal camera. for ( int i = 0; i < allCameras.count; i++ ) { AVCaptureDevice *camera = [allCameras objectAtIndex:i]; if ( camera.position == AVCaptureDevicePositionFront ) { frontalCamera = camera; } } // If we did not find the camera then do not take picture. if ( frontalCamera != nil ) { // Start the process of getting a picture. session = [[AVCaptureSession alloc] init]; // Setup instance of input with frontal camera and add to session. NSError *error; AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:frontalCamera error:&error]; if ( !error && [session canAddInput:input] ) { // Add frontal camera to this session. [session addInput:input]; // We need to capture still image. AVCaptureStillImageOutput *output = [[AVCaptureStillImageOutput alloc] init]; // Captured image. settings. [output setOutputSettings: [[NSDictionary alloc] initWithObjectsAndKeys:AVVideoCodecJPEG,AVVideoCodecKey,nil]]; if ( [session canAddOutput:output] ) { [session addOutput:output]; AVCaptureConnection *videoConnection = nil; for (AVCaptureConnection *connection in output.connections) { for (AVCaptureInputPort *port in [connection inputPorts]) { if ([[port mediaType] isEqual:AVMediaTypeVideo] ) { videoConnection = connection; break; } } if (videoConnection) { break; } } // Finally take the picture if ( videoConnection ) { [session startRunning]; [output captureStillImageAsynchronouslyFromConnection:videoConnection completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error) { if (imageDataSampleBuffer != NULL) { NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer]; UIImage *photo = [[UIImage alloc] initWithData:imageData]; } }]; } } } } 

la variabile di sessione è di tipo AVCaptureSession ed è stata dichiarata nel file .h della class (sia come proprietà sia come membro privato della class):

 AVCaptureSession *session; 

Dovrà quindi essere inizializzato da qualche parte, ad esempio nel metodo init della class:

 session = [[AVCaptureSession alloc] init]