美文网首页
利用AVFoundation实现二维码扫描

利用AVFoundation实现二维码扫描

作者: LeeTrombone | 来源:发表于2016-07-15 17:41 被阅读0次

    主要涉及的类:

    AVCaptureDevice代表了物理捕获设备如:摄像机。用于配置等底层硬件设置相机的自动对焦模式。
    
    AVCaptureDeviceInput是AVCaptureInput的子类,可以作为输入捕获会话,用AVCaptureDevice实例初始化。
    
    AVCaptureSession管理输入(AVCaptureInput)和输出(AVCaptureOutput)流,包含开启和停止会话方法。
    
    AVCaptureMetadataOutput是AVCaptureOutput的子类,处理输出捕获会话。捕获的对象传递给一个委托实线AVCaptureMetadataOutputObjectsDelegate协议。协议方法在指定的派发队列(dispatch queue)上执行。
    
    AVCaptureVideoPreviewLayer是CALayer的一个子类,显示捕获到的相机输出流。
    

    实现的基本流程如下:

    1.首先获取流媒体信息我们需要用到AVCaptureSession对象来管理输入流和输出流;

    2.然后利用AVCaptureVideoPreviewLayer对象来显示信息。

    二维码扫描流程图.jpg

    下面开始上代码了...

    1.导入AVFoundation Framework的头文件,并添加AVCaptureSession和AVCaptureVideoPreviewLayer的属性

    #import "QRCodeScanViewController.h"
    #import <AVFoundation/AVFoundation.h>
    
    @interface QRCodeScanViewController () <AVCaptureMetadataOutputObjectsDelegate>
    
    @property (nonatomic, strong) AVCaptureSession *captureSession;
    @property (nonatomic, strong) AVCaptureVideoPreviewLayer *previewLayer;
    // 闪关灯开启关闭标志
    @property (nonatomic, assign) BOOL isLightOn;
    @end
    

    2.创建会话,读取输入流

    // 开始扫描
    - (BOOL)startScan {
        // 获取手机硬件设备
        AVCaptureDevice *captureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
        // 初始化输入流
        NSError *error = nil;
        AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:captureDevice error:&error];
        if (!input) {
            NSLog(@"%@",[error localizedDescription]);
            return NO;
        }
        // 创建会话
        _captureSession = [[AVCaptureSession alloc] init];
        // 添加输入流
        [_captureSession addInput:input];
        // 初始化输出流
        AVCaptureMetadataOutput *output = [[AVCaptureMetadataOutput alloc] init];
        // 添加输出流
        [_captureSession addOutput:output];
        // 创建dispatch queue
        dispatch_queue_t queue = dispatch_queue_create(kQRCodeScanQueueName, DISPATCH_QUEUE_CONCURRENT);
        //扫描的结果苹果是通过代理的方式区回调,所以outPut需要添加代理,并且因为扫描是耗时的工作,所以把它放到子线程里面
        [output setMetadataObjectsDelegate:self queue:queue];
        // 设置支持二维码和条形码扫描
        [output setMetadataObjectTypes:@[AVMetadataObjectTypeQRCode]];
        // 创建输出对象
        _previewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:_captureSession];
        [_previewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];
        _previewLayer.frame = self.view.bounds;
        [self.view.layer insertSublayer:_previewLayer atIndex:0];
        // 开始会话
        [_captureSession startRunning];
        return YES;
    }
    

    3.结束扫描

    // 结束扫描
    - (void)stopScan {
        // 停止会话
        [_captureSession stopRunning];
        _captureSession = nil;
    }
    

    4.获取扫描结果并处理

    #pragma mark -- AVCaptureMetadataOutputObjectsDelegate
    // 扫描结果的代理回调方法
    - (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection {
        if (metadataObjects != nil && metadataObjects.count > 0) {
            // 扫描到之后,停止扫描
            [self stopScan];
            // 获取结果并对其进行处理
            AVMetadataMachineReadableCodeObject *object = metadataObjects.firstObject;
            if ([[object type] isEqualToString:AVMetadataObjectTypeQRCode]) {
                NSString *result = object.stringValue;
                // 处理result
                NSLog(@"%@",result);
            } else {
                NSLog(@"不是二维码");
            }
        }
    }
    

    5.通常在扫描的时候会有开启闪光灯的功能,也是通过AVCaptureDevice来实现的。添加isLightOn属性,设置初始值为NO,并添加开关闪光灯的按钮

    // 开启和关闭闪光灯
    - (IBAction)didClickedLightUpButton:(UIButton *)sender {
        AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
        //判断手机是否有闪光灯
        if ([device hasTorch]) {
            //呼叫手机操作系统,控制手机硬件
            NSError *error = nil;
            [device lockForConfiguration:&error];
            if (self.isLightOn == NO) {
                [device setTorchMode:AVCaptureTorchModeOn];
                self.isLightOn = YES;
            } else {
                [device setTorchMode:AVCaptureTorchModeOff];
                self.isLightOn = NO;
            }
            //结束对硬件的控制,跟上面的lockForConfiguration是配对的API
            [device unlockForConfiguration];
        }
    }
    

    最后附上github地址:https://github.com/chocklee/QRCodeScan

    相关文章

      网友评论

          本文标题:利用AVFoundation实现二维码扫描

          本文链接:https://www.haomeiwen.com/subject/abpyjttx.html