Ios 在不显示控件的情况下在iPhone上拍照

Ios 在不显示控件的情况下在iPhone上拍照,ios,camera,Ios,Camera,有没有一种方法可以在iPhone上用代码拍照,而不用通过苹果的控制?我见过很多这样做的应用程序,但我不确定使用哪种API调用。是的,有两种方法可以做到这一点。iOS 3.0+中提供的一种方法是使用UIImagePickerController类,将ShowScameraControl属性设置为NO,并将cameraOverlayView属性设置为您自己的自定义控件。第二,iOS 4.0+中提供的功能是配置AVCaptureSession,使用适当的相机设备为其提供AVCaptureDeviceI

有没有一种方法可以在iPhone上用代码拍照,而不用通过苹果的控制?我见过很多这样做的应用程序,但我不确定使用哪种API调用。

是的,有两种方法可以做到这一点。iOS 3.0+中提供的一种方法是使用
UIImagePickerController
类,将
ShowScameraControl
属性设置为NO,并将
cameraOverlayView
属性设置为您自己的自定义控件。第二,iOS 4.0+中提供的功能是配置
AVCaptureSession
,使用适当的相机设备为其提供
AVCaptureDeviceInput
,以及
AVCaptureStillImageOutput
。第一种方法简单得多,适用于更多的iOS版本,但第二种方法使您能够更好地控制照片分辨率和文件选项。

编辑:正如下面的评论所建议的,我现在已经明确说明了需要如何声明和初始化AVCaptureSession。似乎有一些人的初始化错误,或者在方法中将AVCaptureSession声明为局部变量。这是行不通的

以下代码允许使用AVCaptureSession拍照,无需用户输入:

// 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];                                                                 
                    }

                }];
            }
        }
    }
}
然后需要在某个地方初始化它,例如在类的init方法中:

session = [[AVCaptureSession alloc] init]

假设你的意思是不使用UIImagePickerController,那么你可以使用“Apple控件”。现在试试这段代码,直到
[output captureStillImageAsynchronouslyFromConnection:…
但随后停止,导致照片从未被实际拍摄。我在紧接着这一行添加了日志记录,但它从未被记录。代码与您编写的代码一字不差,我已经确认了代码,直到这一点起作用为止(添加了一个按钮并将其连接到.xib中,可以正常启动)。我还包括了AVFoundation.framework和AssetsLibrary.framework。有什么想法吗?您是否在这一行设置了断点:if(imageDataSampleBuffer!=NULL)是否命中?如果命中,错误是否不为空?当应用程序处于后台模式时,是否有办法使其工作?不确定。您可以尝试录制视频而不是静止图像。录制从前台开始,视频帧将在后台接收。解决了各种海报中指出的回调阻止的问题从不调用[output CaptureShillImageAsynchronousLyfromConnection:…]:不要在函数中本地声明“session”为
AVCaptureSession*session=[[AVCaptureSession alloc]init];
(即在堆栈上)。相反,请使用
@property AVCaptureSession*session;
在.h文件中将其声明为属性,否则,在调用回调块时,它将消失。OP注意到了这一点,但添加到原始代码中以明确说明会有所帮助。
session = [[AVCaptureSession alloc] init]