Ricardo RendonCepeda Ricardo RendonCepeda - 5 months ago 49
iOS Question

iOS 7 AVCaptureMetadataOutput delegate (QRCode scanner)

I'm trying to implement a QRCode scanner with the new iOS 7 features but my code isn't calling the main

AVCaptureMetadataOutputObjectsDelegate
method.

I've used the AVFoundation camera before and with my current implementation I've got the preview layer running without a problem. Even switching my output back to
AVCaptureVideoDataOutput
validates my session setup.

I'm using this NSHipster post as a guideline and here's my code so far:

Interface:

@import AVFoundation;

@interface QRCodeViewController () <AVCaptureMetadataOutputObjectsDelegate>

@property (strong, nonatomic) AVCaptureDevice* device;
@property (strong, nonatomic) AVCaptureDeviceInput* input;
@property (strong, nonatomic) AVCaptureMetadataOutput* output;
@property (strong, nonatomic) AVCaptureSession* session;
@property (strong, nonatomic) AVCaptureVideoPreviewLayer* preview;

@end


Setup:

- (void)setupCamera
{
// Device
self.device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];

// Input
self.input = [AVCaptureDeviceInput deviceInputWithDevice:self.device error:nil];

// Output
self.output = [[AVCaptureMetadataOutput alloc] init];
[self.output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];

// Session
self.session = [[AVCaptureSession alloc] init];
[self.session addInput:self.input];
[self.session addOutput:self.output];

// Preview
self.preview = [AVCaptureVideoPreviewLayer layerWithSession:self.session];
self.preview.videoGravity = AVLayerVideoGravityResizeAspectFill;
self.preview.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
[self.view.layer insertSublayer:self.preview atIndex:0];

// Start
[self.session startRunning];
}


Delegate Method:

// DELEGATE METHOD NOT CALLED
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection
{
NSLog(@"Metadata");
}


Any help is greatly appreciated!

Answer

I am trying to figure this out myself. The documentation seems to say that if you don't set the type(s) you want in metadataObjectTypes, you won't get any calls. But my iPad Mini's back camera returns an empty array for availableMetadataObjectTypes. Let us know what you figure out.

Edit:

I just figured out that if you add the AVCaptureMetadataOutput object to the session, the availableMetadataObjectTypes gets filled in and you can add the barcode detector to it. Then the captureOutput delegate will get called, so like this:

AVCaptureMetadataOutput *output = [[AVCaptureMetadataOutput alloc] init];
[output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
[session addOutput:output];
output.metadataObjectTypes = @[AVMetadataObjectTypeQRCode];