• 二维码扫描(iOS原生二维码扫描)


    一、关于二维码扫描的第三方库有很多:例如比较常用的两个

     1.ZBar SDK ZBar为我们提供了两种使用方式,一种是直接调用ZBar提供的ZBarReaderViewController打开一个扫描界面,另一种方式是使用ZBar提供的可以嵌在其他视图中的ZBarReaderView,实际项目中我们更可能会使用第二种方式,这可以让我们对界面做更多的定制,详细的百度查找相关文档来看。

     

     2.ZXing(Github镜像地址)是一个开源的条码生成和扫描库(开源协议为Apache2.0)。它不但支持众多的条码格式,而且有各种语言的实现版本,它支持的语言包括:Java C++ C# Objective-CActionScript以及Ruby;首先去Google CodeGithubZXing的代码下载下来,整个工程比较大,我们只需要其中涉及iOS的部分,所以最好做一些裁剪。简单来说,我们只需要保留cppiphone2个文件夹,其余的全部删掉。

    二、

    1.本次介绍的是:iOS原生二维码扫描,利用iOS7自带的AVFoundation Framework 来实现二维码扫描

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

     

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

     

    1>AVCaptureSession 管理输入(AVCaptureInput)和输出(AVCaptureOutput)流,包含开启和停止会话方法。

    2>AVCaptureDeviceInput AVCaptureInput的子类,可以作为输入捕获会话,用AVCaptureDevice实例初始化。

    3>AVCaptureDevice 代表了物理捕获设备如:摄像机。用于配置等底层硬件设置相机的自动对焦模式。

    4>AVCaptureMetadataOutput AVCaptureOutput的子类,处理输出捕获会话。捕获的对象传递给一个委托实现

    5>AVCaptureMetadataOutputObjectsDelegate协议。协议方法在指定的派发队列(dispatch queue)上执行。

    6>AVCaptureVideoPreviewLayerCALayer的一个子类,显示捕获到的相机输出流。

      1 /*
      2  步骤如下:
      3  1.导入AVFoundation框架,引入<AVFoundation/AVFoundation.h>
      4  2.设置一个用于显示扫描的view
      5  3.实例化AVCaptureSession、AVCaptureVideoPreviewLayer
      6  */
      7 
      8 #import "ViewController.h"
      9 #import <AVFoundation/AVFoundation.h>
     10 @interface ViewController ()<AVCaptureMetadataOutputObjectsDelegate>
     11 
     12 @property (strong,nonatomic) UIView *viewPreview ;
     13 @property (strong,nonatomic) UILabel *lblStatus ;
     14 @property (strong,nonatomic) UIButton *startBtn ;
     15 
     16 @property (strong,nonatomic) UIView *boxView ;
     17 @property (nonatomic) BOOL isReading ;
     18 @property (strong,nonatomic) CALayer *scanLayer;
     19 
     20 -(BOOL)startReading;
     21 -(void)stopReading ;
     22 
     23 //捕捉会话
     24 @property (strong,nonatomic) AVCaptureSession *captureSession;
     25 //展示layer
     26 @property (strong,nonatomic) AVCaptureVideoPreviewLayer *videoPreviewLayer;
     27 
     28 @end
     29 
     30 
     31 @implementation ViewController
     32 
     33 - (void)viewDidLoad {
     34     [super viewDidLoad];
     35 //    self.view.backgroundColor = [UIColor whiteColor];
     36     self.captureSession = nil ;
     37     _isReading = NO ;
     38     [self initUI];
     39     
     40     
     41 }
     42 
     43 -(BOOL)startReading
     44 {
     45     NSError *error;
     46     //1.初始化捕捉设备(AVCaptureDevice),类型为AVMediaTypeVideo
     47     AVCaptureDevice *captureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
     48     //2.用captureDevice创建输入流
     49     AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:captureDevice error:&error];
     50     if (!input) {
     51         NSLog(@"%@",[error localizedDescription]);
     52         return NO ;
     53     }
     54     //3.创建媒体数据输出流
     55     AVCaptureMetadataOutput *captureMetadataOutput = [[AVCaptureMetadataOutput alloc] init];
     56 //    AVCaptureOutput *outPut = [[AVCaptureOutput alloc] init];
     57     //4.实例化捕捉会话
     58     _captureSession = [[AVCaptureSession alloc] init];
     59     //4.1将输入流添加带会话
     60     [_captureSession addInput:input];
     61     //4.2将媒体输出流添加带会话中
     62     [_captureSession addOutput:captureMetadataOutput];
     63     //5.创建串行队列,并加媒体输出流添加到队列当中
     64     dispatch_queue_t dispatchQueue;
     65     dispatchQueue = dispatch_queue_create("myQueue", NULL);
     66     //5.1.设置代理
     67 //    [captureMetadataOutput setMetadataObjectsDelegate:self queue:dispatchQueue];
     68     //
     69     //设置代理 刷新线程
     70     [captureMetadataOutput setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
     71     //5.2.设置输出媒体数据类型为QRCode
     72 //    [captureMetadataOutput setMetadataObjectTypes:[NSArray arrayWithObject:AVMetadataObjectTypeQRCode]];
     73     if (captureMetadataOutput) {
     74         
     75         //设置扫码支持的编码格式
     76         NSMutableArray *array = [[NSMutableArray alloc] initWithCapacity:0];
     77         
     78         if ([captureMetadataOutput.availableMetadataObjectTypes containsObject:AVMetadataObjectTypeQRCode]) {
     79             [array addObject:AVMetadataObjectTypeQRCode];
     80         }
     81         if ([captureMetadataOutput.availableMetadataObjectTypes containsObject:AVMetadataObjectTypeEAN13Code]) {
     82             [array addObject:AVMetadataObjectTypeEAN13Code];
     83         }
     84         if ([captureMetadataOutput.availableMetadataObjectTypes containsObject:AVMetadataObjectTypeEAN8Code]) {
     85             [array addObject:AVMetadataObjectTypeEAN8Code];
     86         }
     87         if ([captureMetadataOutput.availableMetadataObjectTypes containsObject:AVMetadataObjectTypeCode128Code]) {
     88             [array addObject:AVMetadataObjectTypeCode128Code];
     89         }
     90         captureMetadataOutput.metadataObjectTypes = array;
     91     }
     92     
     93     //6.实例化预览图层
     94     _videoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSessionWithNoConnection:_captureSession];
     95     //7.设置预览图层填充方式
     96     [_videoPreviewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];
     97     //8.设置图层的frame
     98     [_videoPreviewLayer setFrame:_viewPreview.layer.bounds];
     99     //9.将图层添加到预览view的图层上
    100     [_viewPreview.layer addSublayer:_videoPreviewLayer];
    101     //10.设置扫描范围
    102     captureMetadataOutput.rectOfInterest = CGRectMake(0.2f, 0.2f, 0.8f, 0.8f);
    103     //10.1扫描框
    104     CGFloat width = _viewPreview.bounds.size.width ;
    105     CGFloat height = _viewPreview.bounds.size.height;
    106     self.boxView = [[UIView alloc] initWithFrame:CGRectMake(width * 0.2f, height * 0.2f, width - width * 0.4f, height - height * 0.4f)];
    107     _boxView.layer.borderColor = [[UIColor greenColor] CGColor];
    108     _boxView.layer.borderWidth = 1.0f ;
    109     [_viewPreview addSubview:_boxView];
    110     //10.2扫描线
    111     self.scanLayer = [[CALayer alloc] init];
    112     _scanLayer.frame = CGRectMake(0, 0, _boxView.bounds.size.width, 1);
    113     _scanLayer.backgroundColor = [[UIColor brownColor] CGColor];
    114     [_boxView.layer insertSublayer:_scanLayer atIndex:0];
    115     NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:0.2f target:self selector:@selector(moveScanLayer:) userInfo:nil repeats:YES];
    116     [timer fire];
    117     //10.开始扫描
    118     [_captureSession startRunning];
    119     return YES ;
    120 }
    121 
    122 
    123 -(void)stopReading{
    124     [_captureSession stopRunning];
    125     _captureSession = nil;
    126     [_scanLayer removeFromSuperlayer];
    127     [_videoPreviewLayer removeFromSuperlayer];
    128 }
    129 
    130 #pragma mark --实现计时器方法moveScanLayer:(NSTimer *)timer
    131 
    132 - (void)moveScanLayer:(NSTimer *)timer
    133 {
    134     CGRect frame = _scanLayer.frame;
    135     if (_boxView.frame.size.height < _scanLayer.frame.origin.y) {
    136         frame.origin.y = 0;
    137         _scanLayer.frame = frame;
    138     }else{
    139         frame.origin.y += 5;
    140         [UIView animateWithDuration:0.1 animations:^{
    141             _scanLayer.frame = frame;
    142         }];
    143     }
    144 }
    145 
    146 #pragma mark --初始化控件
    147 -(void)initUI
    148 {
    149     self.viewPreview = [[UIView alloc] init];
    150     self.viewPreview.frame = CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height -200);
    151 //    self.viewPreview.backgroundColor = [UIColor clearColor];
    152 //    self.viewPreview.alpha = 0.1f ;
    153     [self.view addSubview:_viewPreview];
    154     
    155     self.startBtn = [UIButton buttonWithType:UIButtonTypeSystem];
    156     _startBtn.frame = CGRectMake(100, self.view.bounds.size.height - 100, 175, 30);
    157     [_startBtn setTitle:@"开始" forState:UIControlStateNormal];
    158     [_startBtn addTarget:self action:@selector(startStopReading:) forControlEvents:UIControlEventTouchUpInside];
    159     [self.view addSubview:_startBtn];
    160 }
    161 
    162 #pragma mark --实现开始和停止方法
    163 -(void)startStopReading:(UIButton *)btn
    164 {
    165     if (!_isReading) {
    166         
    167         if ([self startReading]) {
    168             [_startBtn setTitle:@"停止" forState:UIControlStateNormal];
    169         }
    170     }
    171     else
    172     {
    173             [self stopReading];
    174             [_startBtn setTitle:@"开始" forState:UIControlStateNormal];
    175     }
    176     
    177     _isReading = !_isReading ;
    178 }
    179 
    180 - (void)didReceiveMemoryWarning {
    181     [super didReceiveMemoryWarning];
    182     // Dispose of any resources that can be recreated.
    183 }
    184 
    185 
    186 #pragma mark --实现AVCaptureMetadataOutputObjectsDelegate协议方法
    187 -(void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection
    188 {
    189     if (metadataObjects.count > 0) {
    190         AVMetadataMachineReadableCodeObject *metadataObject = [metadataObjects firstObject];
    191          NSLog(@"................%@",metadataObject.stringValue);
    192         [self performSelectorOnMainThread:@selector(stopReading) withObject:nil waitUntilDone:NO];
    193 
    194     }
    195 }
    196 
    197 
    198 - (BOOL)shouldAutorotate
    199 {
    200     return NO;
    201 }
    202 @end

     

  • 相关阅读:
    深入理解C++ 11新特性:1)
    Effective Java 第三版:1)
    Java 8 实战:2)
    MyBatis Plus
    Java 8 实战:1)
    十二要素应用宣言
    Dubbo 2):源码级
    [SCOI2009]windy数 数位dp
    [ZJOI2006]物流运输 最短路 动态规划
    [ZJOI2008]骑士
  • 原文地址:https://www.cnblogs.com/yyxblogs/p/5128045.html
Copyright © 2020-2023  润新知