二维码扫描(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

 

 

posted @ 2016-01-13 17:57  YX祥  阅读(446)  评论(0编辑  收藏  举报