AVFoundation框架 二维码扫描

  iOS 7 之前一直都是使用第三方的框架实现二维码扫描,比如ZBar和ZXing。感兴趣的可以去搜这两个开源的库用用。不过iOS 7 之后苹果出了相应的原生API处理二维码的扫描。效率上感觉原生的还是要好一点,应用中使用的时候,扫描一维码还是比较费劲,不知道微信的条形码扫描是用什么做的,扫描挺快的。

  首先借一张图了解一下AVFoundation框架

                  

  AVFoundation 是一个很大基础库,用它来处理媒体相关的操作。本文只是用它实现二维码扫描,想了解更多功能,请查阅官网API。实现二维码扫描需要使用的类及其子类

  • AVCaptureDevice 代表了输入设备,例如摄像头与麦克风
  • AVCaptureInput 代表了输入数据源
  • AVCaptureDeviceInput 是AVCaptureInput的子类,可以作为输入捕获会话,用AVCaptureDevice实例初始化。
  • AVCaptureOutput 代表了输出数据源
  • AVCaptureMetadataOutput 是AVCaptureOutput的子类,处理输出捕获会话。捕获的对象传递给一个委托实现
  • AVCaptureSession 用于协调输入与输出之间的数据流

  使用demo。TP

  1. 创建AVCaptureSession对象,首先导入头文件#import <AVFoundation/AVFoundation.h>
    //新建session
    AVCaptureSession *session = [[AVCaptureSession alloc] init];
    self.session = session;

  2. 创建一个AVCaptureDevice代表代表输入设备。在这里我们制定设备用于摄像

    //新建device Type是一个枚举:AVMediaTypeAudio,AVMediaTypeVideo,AVMediaTypeMetadata
    AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];

  3.  创建AVCaptureDeviceInput,并添加到Session中,我们需要使用AVCaptureDeviceInput来让设备添加到session中, AVCaptureDeviceInput负责管理设备端口。我们可以理解它为设备的抽象。一个设备可能可以同时提供视频和音频的捕捉。我们可以分别用AVCaptureDeviceInput来代表视频输入和音频输入。

    //新建output并添加到session
    AVCaptureMetadataOutput *output = [[AVCaptureMetadataOutput alloc]init];
    dispatch_queue_t dispathcQueue;
    dispathcQueue = dispatch_queue_create("myQueue", nil);
    [output setMetadataObjectsDelegate:self queue:dispathcQueue];
    [session addOutput:output];
    //这里注意要把这代码写在,output添加到session后,否则会闪退。
    [output setMetadataObjectTypes:@[AVMetadataObjectTypeQRCode]];

 

 

  4.  新建AVCaptureVideoPreviewLayer,显示output的内容

AVCaptureVideoPreviewLayer *viewLayer = [[AVCaptureVideoPreviewLayer alloc]initWithSession:session];
    viewLayer.frame = self.view.bounds;
    [self.view.layer addSublayer:viewLayer];
    
    [session startRunning];

  demo很简单,不想手写代码的同学可以到gitHub上下载代码 TP

  项目中往往要比demo要求的多,实际项目中遇到的问题,在这给大家分享一下,希望对遇到同样问题的人能有所帮助,如果你有更好的解决方案@me。

  1.  实现微信里扫描时,二维码图片显示的比较大。

  我的解决方案是,对viewLayer进行放大

self.Videolayer.transform = CATransform3DMakeScale(2, 2, 1);//图像放大

     2.  扫描时需要指定扫描的区域

  output类有个属性rectOfInterest可以设置扫描的区域,这里有个坑,这个区域的原点是右上角,并且width 和 height也是和正常的反过来。值是0-1之间的小数,是占屏幕的百分比。

  3.  如果应用在使用相机时被用户拒绝,可以获得当前的状态,并提示用户

    //隐私里设置
        AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];

 

posted @ 2015-12-08 16:50  yzVictory  阅读(1684)  评论(0编辑  收藏  举报