iOS原生二维码扫描实现

2016-03-11  本文已影响137人  李逍遥_
通常我们用到的二维码扫描可能还是首先想到ZXing或者ZBar,但是用第三方的会有很多不变,第一是因入库文件占用内存较大,第二就是使用不方便,效率不够高;所以在iOS7系统中苹果引入了自己的二维码扫描机制,那效率必然是无话可说的,废话不多说,直接开始——

1.引入头文件

#import <AVFoundation/AVFoundation.h>

2.声明相关类属性

//设备属性
@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;

3.设置代理方法

@interface TA_qrcode_home ()<AVCaptureMetadataOutputObjectsDelegate>

4.扫描主体实现

#pragma mark -----初始化相机设备等扫描控件------
- (void)setupCamera
{
    // Device
    _device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    
    if(_device == nil)
    {
        UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"未检测到相机设备" message:@"未检测到相机设备" delegate:self cancelButtonTitle:nil otherButtonTitles:@"确定", nil];
        [alert show];
        return ;
    }
    // Input
    _input = [AVCaptureDeviceInput deviceInputWithDevice:self.device error:nil];
    // Output
    _output = [[AVCaptureMetadataOutput alloc]init];
    [_output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
    // Session
    _session = [[AVCaptureSession alloc]init];
    //限制扫描区域
    CGSize size = self.view.bounds.size;
    CGRect cropRect = self.sweepFrame;
    CGFloat p1 = size.height/size.width;
    CGFloat p2 = 1920./1080.;  //使用了1080p的图像输出
    if (p1 < p2) {
        CGFloat fixHeight = size.width * 1920. / 1080.;
        CGFloat fixPadding = (fixHeight - size.height)/2;
        _output.rectOfInterest = CGRectMake((cropRect.origin.y + fixPadding)/fixHeight,cropRect.origin.x/size.width,cropRect.size.height/fixHeight,cropRect.size.width/size.width);
    } else {
        CGFloat fixWidth = size.height * 1080. / 1920.;
        CGFloat fixPadding = (fixWidth - size.width)/2;
        _output.rectOfInterest = CGRectMake(cropRect.origin.y/size.height,(cropRect.origin.x + fixPadding)/fixWidth,cropRect.size.height/size.height,cropRect.size.width/fixWidth);
    }
    [_session setSessionPreset:AVCaptureSessionPresetHigh];
    if ([_session canAddInput:self.input])
    {
        [_session addInput:self.input];
    }
    
    if ([_session canAddOutput:self.output])
    {
        [_session addOutput:self.output];
    }
    NSLog(@"%@",[_output availableMetadataObjectTypes]);
    // 扫码类型 AVMetadataObjectTypeQRCode,此为支持所有扫描类型
    [_output setMetadataObjectTypes:[NSArray arrayWithObjects:AVMetadataObjectTypeEAN13Code, AVMetadataObjectTypeEAN8Code, AVMetadataObjectTypeCode128Code, AVMetadataObjectTypeQRCode, nil]];
    // Preview
    _preview =[AVCaptureVideoPreviewLayer layerWithSession:self.session];
    _preview.videoGravity = AVLayerVideoGravityResizeAspectFill;
    _preview.frame =CGRectMake(0,0,ScreenFrameWidth,ScreenFrameHeight-44);
    [self.view.layer insertSublayer:self.preview atIndex:0];
    // Start
    [_session startRunning];
}

5.如何做到扫描区域的限制
参看连接,非常详尽讲解:http://www.jianshu.com/p/3fb24fc7b415

6.代理回调方法

#pragma mark -----AVCaptureMetadataOutputObjectsDelegate
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection
{
    
    if ([metadataObjects count] >0)
    {
        AVMetadataMachineReadableCodeObject * metadataObject = [metadataObjects objectAtIndex:0];
        
        self.resultStr = metadataObject.stringValue;
    }
    [self stopDevice];
    ...
}
-(void)stopDevice
{
    [_session stopRunning];
    _session = nil;
    [self.preview removeFromSuperlayer];
    [self.sweepViewHandler.timer invalidate];
}

7.视图区域的绘制(好多人以为这个设置出来效果就是我们平时的视图小效果就是调用设备即可,其实不然,是需要手动绘制的,这里不多赘述)

这篇文章写得不错,有需要可以参考 http://www.jianshu.com/p/05949cc8f7af

上一篇下一篇

猜你喜欢

热点阅读