Osheep

时光不回头,当下最重要。

原生二维码扫描

基本知识

  • AVCaptureSession
    AVCaptureSession的中央枢纽AVFoundation捕获类
  • AVCaptureDevice
    代表一个物理设备,提供实时输入媒体数据,如视频和音频
  • AVCaptureInput
    是AVCaptureInput的子类,可以作为输入捕获会话
  • AVCaptureMetadataOutput
    处理输出捕获会话,需要指定他的输出类型及扫描范围
  • AVCaptureVideoPreviewLayer
    显示捕获到的相机输出流,提供摄像头的预览功能

扫描步骤

  1. 创建AVCaputureSession
    作为协调输入与输出的中心,我们第一步需要创建一个Session

    _captureSession = [[AVCaptureSession alloc]init];
    
  2. 创建AVCaptureDevice
    创建一个AVCaptureDevice代表代表输入设备

    _captureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    
  3. 创建AVCaptureDeviceInput,并添加到Session中
    AVCaptureDeviceInput负责管理设备端口。我们可以理解它为设备的抽象。一个设备可能可以同时提供视频和音频的捕捉。

    _deviceInput = [[AVCaptureDeviceInput alloc]initWithDevice:_captureDevice error:&error];
    [_captureSession addInput:_deviceInput];
    
  4. 创建AVCaptureOutput,并添加到Session中
    为了从session中取得数据,我们需要创建一个AVCaptureMetadataOutput

    _captureMetadataOutPut = [[AVCaptureMetadataOutput alloc]init];
    [_captureSession addOutput:_captureMetadataOutPut];
    
  5. 设置 AVCaptureMetadataOutput的delegate和扫描类型以及扫描区域
    需要指定特定的扫描区域AVCaptureMetadataOutput的rectOfInterest,AVCapture输出的图片大小都是横着的,而iPhone的屏幕是竖着的,那么我把它旋转90°才正确。

    [_captureMetadataOutPut setMetadataObjectsDelegate:self queue:dispatch_queue_create("ease_capture_queue",NULL)];
    [_captureMetadataOutPut setMetadataObjectTypes:[NSArray arrayWithObject:AVMetadataObjectTypeQRCode]];
    _captureMetadataOutPut.rectOfInterest = CGRectMake(0,0,1,1);
    
  6. 设置AVCaptureVideoPreviewLayer,开始扫描
    显示捕获到的相机输出流

    _previewLayer = [AVCaptureVideoPreviewLayer layerWithSession:_captureSession];
        [_previewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];
    
    [self.previewLayer.session startRunning];
    
  7. AVCaptureMetadataOutputObjectsDelegate获取扫描结果
    - (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection{
     //判断是否有数据,是否是二维码数据
     if (metadataObjects.count > 0) {
         __block AVMetadataMachineReadableCodeObject *result = nil;
         [metadataObjects enumerateObjectsUsingBlock:^(AVMetadataMachineReadableCodeObject *obj, NSUInteger idx, BOOL *stop) {
             if ([obj.type isEqualToString:AVMetadataObjectTypeQRCode]) {
                 result = obj;
                 *stop = YES;
             }
         }];
         if (!result) {
             result = [metadataObjects firstObject];
         }
         dispatch_async(dispatch_get_main_queue(), ^{
             [self analyseResult:result];
         });
     }
    

demo链接

https://github.com/CaoXueLiang/ScanQrCode

点赞