• iOS-AVFoundation实现二维码(ios7以上,转载)


    关于二维码扫描有不少优秀第三方库

    关于AVFoundation

    AVFoundation 是一个很大基础库,用来创建基于时间的视听媒体,可以使用它来检查,创建、编辑或媒体文件。也可以输入流从设备和操作视频实时捕捉和回放。详细框架介绍见官网:About AV Foundation,本文只是介绍如果使用AVFoundation获取二维码。

    首先获取流媒体信息我们需要AVCaptureSession对象来管理输入流和输出流,AVCaptureVideoPreviewLayer对象来显示信息

    注:

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

    下面看下实现过程如下:

    Step1:需要导入:AVFoundation Framework 包含头文件:

    #import <AVFoundation/AVFoundation.h>
    实现<AVCaptureMetadataOutputObjectsDelegate>协议

    Step2:设置捕获会话

    设置 AVCaptureSession 和 AVCaptureVideoPreviewLayer 成员

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
        #import <AVFoundation/AVFoundation.h>
    
        static const char *kScanQRCodeQueueName = "ScanQRCodeQueue";
    
        @interface ViewController () <AVCaptureMetadataOutputObjectsDelegate>
        .....
        @property (nonatomic) AVCaptureSession *captureSession;
        @property (nonatomic) AVCaptureVideoPreviewLayer *videoPreviewLayer;
        @property (nonatomic) BOOL lastResult;
        @end
    

    Step3:创建会话,读取输入流

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    
        - (BOOL)startReading
        {
            // 获取 AVCaptureDevice 实例
            NSError * error;
            AVCaptureDevice *captureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
            // 初始化输入流
            AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:captureDevice error:&error];
            if (!input) {
                NSLog(@"%@", [error localizedDescription]);
                return NO;
            }
            // 创建会话
            _captureSession = [[AVCaptureSession alloc] init];
            // 添加输入流
            [_captureSession addInput:input];
            // 初始化输出流
            AVCaptureMetadataOutput *captureMetadataOutput = [[AVCaptureMetadataOutput alloc] init];
            // 添加输出流
            [_captureSession addOutput:captureMetadataOutput];
    
            // 创建dispatch queue.
            dispatch_queue_t dispatchQueue;
            dispatchQueue = dispatch_queue_create(kScanQRCodeQueueName, NULL);
            [captureMetadataOutput setMetadataObjectsDelegate:self queue:dispatchQueue];
            // 设置元数据类型 AVMetadataObjectTypeQRCode
            [captureMetadataOutput setMetadataObjectTypes:[NSArray arrayWithObject:AVMetadataObjectTypeQRCode]];
    
            // 创建输出对象
            _videoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:_captureSession];
            [_videoPreviewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];
            [_videoPreviewLayer setFrame:_sanFrameView.layer.bounds];
            [_sanFrameView.layer addSublayer:_videoPreviewLayer];
            // 开始会话
            [_captureSession startRunning];
    
            return YES;
        }
    

    Step4:停止读取

    1
    2
    3
    4
    5
    6
    7
    
        - (void)stopReading
        {
            // 停止会话
            [_captureSession stopRunning];
            _captureSession = nil;
        }
    

    Step5:获取捕获数据

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    
    -(void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects
      fromConnection:(AVCaptureConnection *)connection
    {
        if (metadataObjects != nil && [metadataObjects count] > 0) {
            AVMetadataMachineReadableCodeObject *metadataObj = [metadataObjects objectAtIndex:0];
            NSString *result;
            if ([[metadataObj type] isEqualToString:AVMetadataObjectTypeQRCode]) {
                result = metadataObj.stringValue;
            } else {
                NSLog(@"不是二维码");
            }
            [self performSelectorOnMainThread:@selector(reportScanResult:) withObject:result waitUntilDone:NO];
        }
    }
    

    Step6:处理结果

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    
      - (void)reportScanResult:(NSString *)result
      {
          [self stopReading];
          if (!_lastResult) {
              return;
          }
          _lastResut = NO;
          UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"二维码扫描"
                                                          message:result
                                                         delegate:nil
                                                cancelButtonTitle:@"取消"
                                                otherButtonTitles: nil];
          [alert show];
          // 以下处理了结果,继续下次扫描
          _lastResult = YES;
      }
    

    以上基本就是二维码的获取流程,和扫一扫二维码伴随的就是开启系统照明,这个比较简单,也是利用 AVCaptureDevice,请看如下实现:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    
      - (void)systemLightSwitch:(BOOL)open
      {
          AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
          if ([device hasTorch]) {
              [device lockForConfiguration:nil];
              if (open) {
                  [device setTorchMode:AVCaptureTorchModeOn];
              } else {
                  [device setTorchMode:AVCaptureTorchModeOff];
              }
              [device unlockForConfiguration];
          }
      }
    

    以上就是本文介绍的大部分内容,详细代码请看demo  https://github.com/strivingboy/scan_qrcode_demo

  • 相关阅读:
    PHP工程师学Python数据类型
    通过PHP与Python代码对比浅析语法差异
    “adobe premiere中画面和声音不同步” 解决方法
    Web安全之XSS Platform搭建及使用实践
    使用docker快速搭建Permeate渗透测试系统实践
    Web安全开发规范手册V1.0
    遭受刷验证码攻击后的企安建设规划感想
    基于Docker搭建Jumpserver堡垒机操作实践
    使用PHP结合Ffmpeg快速搭建流媒体服务实践
    通过代码审计找出网站中的XSS漏洞实战(三)
  • 原文地址:https://www.cnblogs.com/linxiu-0925/p/5405256.html
Copyright © 2020-2023  润新知