做iOS的二维码扫描,有两个第三方库可以选择,ZBar和ZXing。今天要介绍的是iOS7.0后AVFoundation框架提供的原生二维码扫描。

首先需要添加AVFoundation.framework框架到你工程中build phase的"Link Binary With Libraries"之下,然后就可以开始了。

  一、做好准备工作,搭建UI

  UI效果如图

  IBOutlet、IBAction如下:

@property (weak, nonatomic) IBOutlet UIView *viewPreview;
@property (weak, nonatomic) IBOutlet UILabel *lblStatus;
@property (weak, nonatomic) IBOutlet UIButton *startBtn;
- (IBAction)startStopReading:(id)sender;

  接下来就都是代码的事情了

  二、控制器ViewController.h

  首先导入AVFoundation框架

#import <AVFoundation/AVFoundation.h>

  然后控制器实现AVCaptureMetadataOutputObjectsDelegate协议

@interface ViewController ()<AVCaptureMetadataOutputObjectsDelegate>

  整体property如下:

@property (strong, nonatomic) UIView *boxView;
@property (nonatomic) BOOL isReading;
@property (strong, nonatomic) CALayer *scanLayer; -(BOOL)startReading;
-(void)stopReading; //捕捉会话
@property (nonatomic, strong) AVCaptureSession *captureSession;
//展示layer
@property (nonatomic, strong) AVCaptureVideoPreviewLayer *videoPreviewLayer;

  然后在ViewDidLoad方法中初始化

- (void)viewDidLoad {
[super viewDidLoad]; _captureSession = nil;
_isReading = NO; }

  接下来实现startReading方法(这可就是重点咯)

- (BOOL)startReading {
NSError *error; //1.初始化捕捉设备(AVCaptureDevice),类型为AVMediaTypeVideo
AVCaptureDevice *captureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; //2.用captureDevice创建输入流
AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:captureDevice error:&error];
if (!input) {
NSLog(@"%@", [error localizedDescription]);
return NO;
} //3.创建媒体数据输出流
AVCaptureMetadataOutput *captureMetadataOutput = [[AVCaptureMetadataOutput alloc] init]; //4.实例化捕捉会话
_captureSession = [[AVCaptureSession alloc] init]; //4.1.将输入流添加到会话
[_captureSession addInput:input]; //4.2.将媒体输出流添加到会话中
[_captureSession addOutput:captureMetadataOutput]; //5.创建串行队列,并加媒体输出流添加到队列当中
dispatch_queue_t dispatchQueue;
dispatchQueue = dispatch_queue_create("myQueue", NULL);
//5.1.设置代理
[captureMetadataOutput setMetadataObjectsDelegate:self queue:dispatchQueue]; //5.2.设置输出媒体数据类型为QRCode
[captureMetadataOutput setMetadataObjectTypes:[NSArray arrayWithObject:AVMetadataObjectTypeQRCode]]; //6.实例化预览图层
_videoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:_captureSession]; //7.设置预览图层填充方式
[_videoPreviewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill]; //8.设置图层的frame
[_videoPreviewLayer setFrame:_viewPreview.layer.bounds]; //9.将图层添加到预览view的图层上
[_viewPreview.layer addSublayer:_videoPreviewLayer]; //10.设置扫描范围
captureMetadataOutput.rectOfInterest = CGRectMake(0.2f, 0.2f, 0.8f, 0.8f); //10.1.扫描框
_boxView = [[UIView alloc] initWithFrame:CGRectMake(_viewPreview.bounds.size.width * 0.2f, _viewPreview.bounds.size.height * 0.2f, _viewPreview.bounds.size.width - _viewPreview.bounds.size.width * 0.4f, _viewPreview.bounds.size.height - _viewPreview.bounds.size.height * 0.4f)];
_boxView.layer.borderColor = [UIColor greenColor].CGColor;
_boxView.layer.borderWidth = 1.0f; [_viewPreview addSubview:_boxView]; //10.2.扫描线
_scanLayer = [[CALayer alloc] init];
_scanLayer.frame = CGRectMake(, , _boxView.bounds.size.width, );
_scanLayer.backgroundColor = [UIColor brownColor].CGColor; [_boxView.layer addSublayer:_scanLayer]; NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:0.2f target:self selector:@selector(moveScanLayer:) userInfo:nil repeats:YES];
[timer fire];
//10.开始扫描
[_captureSession startRunning];
return YES;
}

  实现AVCaptureMetadataOutputObjectsDelegate协议方法

#pragma mark - AVCaptureMetadataOutputObjectsDelegate
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection
{
//判断是否有数据
if (metadataObjects != nil && [metadataObjects count] > ) {
AVMetadataMachineReadableCodeObject *metadataObj = [metadataObjects objectAtIndex:];
//判断回传的数据类型
if ([[metadataObj type] isEqualToString:AVMetadataObjectTypeQRCode]) {
[_lblStatus performSelectorOnMainThread:@selector(setText:) withObject:[metadataObj stringValue] waitUntilDone:NO]; [self performSelectorOnMainThread:@selector(stopReading) withObject:nil waitUntilDone:NO];
_isReading = NO;
}
}
}

  实现计时器方法moveScanLayer:(NSTimer *)timer

- (void)moveScanLayer:(NSTimer *)timer
{
CGRect frame = _scanLayer.frame;
if (_boxView.frame.size.height < _scanLayer.frame.origin.y) {
frame.origin.y = ;
_scanLayer.frame = frame;
}else{ frame.origin.y += ; [UIView animateWithDuration:0.1 animations:^{
_scanLayer.frame = frame;
}];
}
}

  实现开始和停止方法

- (IBAction)startStopReading:(id)sender {
if (!_isReading) {
if ([self startReading]) {
[_startBtn setTitle:@"Stop" forState:UIControlStateNormal];
[_lblStatus setText:@"Scanning for QR Code"];
}
}
else{
[self stopReading];
[_startBtn setTitle:@"Start!" forState:UIControlStateNormal];
} _isReading = !_isReading;
} -(void)stopReading{
[_captureSession stopRunning];
_captureSession = nil;
[_scanLayer removeFromSuperlayer];
[_videoPreviewLayer removeFromSuperlayer];
}

  大功告成

  示例源码地址:https://github.com/WuKongCoo1/QRCodeReader

    

iOS:原生二维码扫描的更多相关文章

  1. iOS 原生二维码扫描和生成

    代码地址如下:http://www.demodashi.com/demo/12551.html 一.效果预览: 功能描述:WSLNativeScanTool是在利用原生API的条件下封装的二维码扫描工 ...

  2. iOS 原生二维码扫描(可限制扫描区域)

    篇文章的主要原因不是展示如何使用  AVFoundation 来进行二维码扫描,更主要的是限制扫描二维码的范围.(因为默认的是全屏扫描) 项目遇到扫描二维码的功能需求,这里我放弃了使用三方库,而采用了 ...

  3. 【转】 iOS 原生二维码扫描(可限制扫描区域)

    在用 AVFoundation 完成扫码后,遇到2个问题: 1,如何限制扫描范围? 2.条形码如何扫描? 一位朋友的文章帮助了我,特地转来,可以帮到有需要的朋友. 原文:http://blog.csd ...

  4. iOS 原生二维码扫描,带扫描框和扫描过程动画

    在代码中使用了相对布局框架Masonry 准备两张图片,一张是扫描边框,一张是扫描时的细线分别命名 scanFrame.png和scanLine.png并提前放入工程 导入相对布局头文件 #defin ...

  5. iOS开发-二维码扫描和应用跳转

    iOS开发-二维码扫描和应用跳转   序言 前面我们已经调到过怎么制作二维码,在我们能够生成二维码之后,如何对二维码进行扫描呢? 在iOS7之前,大部分应用中使用的二维码扫描是第三方的扫描框架,例如Z ...

  6. Firemonkey 原生二维码扫描优化

    之前用了ZXing的Delphi版本,运行自带的例子,速度非常慢,与安卓版本的相比查了很多,因此打算使用集成jar的方法,但是总觉得美中不足. 经过一番研究,基本上解决了问题. 主要有两方面的优化: ...

  7. iOS 系统二维码扫描(可限制扫描区域)

    使用 AVFoundation系统库来进行二维码扫描并且限制扫描二维码的范围.(因为默认的是全屏扫描) -(void)beginCode { //1.摄像头设备 AVCaptureDevice *de ...

  8. ios7 苹果原生二维码扫描(和微信类似)

    在ios7苹果推出了二维码扫描,以前想要做二维码扫描,只能通过第三方ZBar与ZXing. ZBar在扫描的灵敏度上,和内存的使用上相对于ZXing上都是较优的,但是对于 “圆角二维码” 的扫描确很困 ...

  9. ipad开发:二维码扫描,摄像头旋转角度问题解决办法

    之前一直是在手机上开发,用系统原生二维码扫描功能,一点问题都没有,但是在ipad上,用户是横屏操作的,虽然界面旋转了,是横屏的,但是摄像头里显示的依然是竖屏效果,也就是说从摄像头里看到的和人眼看到的内 ...

随机推荐

  1. 1.9 需求订单导入MDS

    1.9          需求订单导入MDS 1.9.1   业务方案描述 将”需求订单维护表”中完成调整维护的需求订单导入系统标准MDS中,使之驱动对应的物料需求计划(MRP)的运行. 1.9.2  ...

  2. 低功耗之战!ANT VS Bluetooth LE

    利用近距离无线通信技术将手机及可穿戴式传感器终端等与智能电话连接起来,实现新的功能.最近,以此为目标的行动正在展开.其中备受关注的近距离无线方式是“ANT”和“Bluetooth LE”.为了在各种便 ...

  3. discuz函数dgmdate

    function dgmdate($timestamp, $format = 'dt', $timeoffset = '9999', $uformat = '') { global $_G; $for ...

  4. Codeforces 707D Persistent Bookcase(时间树)

    [题目链接] http://codeforces.com/problemset/problem/707/D [题目大意] 给出一个矩阵,要求满足如下操作,单个位置x|=1或者x&=0,一行的数 ...

  5. CentOS 删除自带的OpenJDK 和 安装SunJDK

    [root@WX32 local]# java -version java version "1.6.0" OpenJDK Runtime Environment (build - ...

  6. Nginx+Tomcat7+Mencached负载均衡集群部署笔记

    Nginx+Tomcat+Memcached负载均衡集群服务搭建 操作系统:CentOS6.5 本文档主要解说,怎样在CentOS6.5下搭建Nginx+Tomcat+Memcached负载均衡集群s ...

  7. ZOJ 3794 Greedy Driver spfa

    题意: 给定n个点,m条有向边,邮箱容量. 起点在1,终点在n,開始邮箱满油. 以下m行表示起点终点和这条边的耗油量(就是长度) 再以下给出一个数字m表示有P个加油站,能够免费加满油. 以下一行P个数 ...

  8. AJAX - 创建 XMLHttpRequest 对象

    XMLHttpRequest 是 AJAX 的基础. XMLHttpRequest 对象 所有现代浏览器均支持 XMLHttpRequest 对象(IE5 和 IE6 使用 ActiveXObject ...

  9. text选中后displa出label内容

    效果很好而且很简单 用text的click属性即可 private sub text1_click()label1.caption="******"label2.caption=& ...

  10. ASP.NET MVC+Entity Framework 4.1访问数据库

    Entity Framework 4.1支持代码优先(code first)编程模式:即可以先创建模型类,然后通过配置在EF4.1下动态生成数据库. 下面演示两种情形: 1.代码优先模式下,asp.n ...