iOS:原生二维码扫描
做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:原生二维码扫描的更多相关文章
- iOS 原生二维码扫描和生成
代码地址如下:http://www.demodashi.com/demo/12551.html 一.效果预览: 功能描述:WSLNativeScanTool是在利用原生API的条件下封装的二维码扫描工 ...
- iOS 原生二维码扫描(可限制扫描区域)
篇文章的主要原因不是展示如何使用 AVFoundation 来进行二维码扫描,更主要的是限制扫描二维码的范围.(因为默认的是全屏扫描) 项目遇到扫描二维码的功能需求,这里我放弃了使用三方库,而采用了 ...
- 【转】 iOS 原生二维码扫描(可限制扫描区域)
在用 AVFoundation 完成扫码后,遇到2个问题: 1,如何限制扫描范围? 2.条形码如何扫描? 一位朋友的文章帮助了我,特地转来,可以帮到有需要的朋友. 原文:http://blog.csd ...
- iOS 原生二维码扫描,带扫描框和扫描过程动画
在代码中使用了相对布局框架Masonry 准备两张图片,一张是扫描边框,一张是扫描时的细线分别命名 scanFrame.png和scanLine.png并提前放入工程 导入相对布局头文件 #defin ...
- iOS开发-二维码扫描和应用跳转
iOS开发-二维码扫描和应用跳转 序言 前面我们已经调到过怎么制作二维码,在我们能够生成二维码之后,如何对二维码进行扫描呢? 在iOS7之前,大部分应用中使用的二维码扫描是第三方的扫描框架,例如Z ...
- Firemonkey 原生二维码扫描优化
之前用了ZXing的Delphi版本,运行自带的例子,速度非常慢,与安卓版本的相比查了很多,因此打算使用集成jar的方法,但是总觉得美中不足. 经过一番研究,基本上解决了问题. 主要有两方面的优化: ...
- iOS 系统二维码扫描(可限制扫描区域)
使用 AVFoundation系统库来进行二维码扫描并且限制扫描二维码的范围.(因为默认的是全屏扫描) -(void)beginCode { //1.摄像头设备 AVCaptureDevice *de ...
- ios7 苹果原生二维码扫描(和微信类似)
在ios7苹果推出了二维码扫描,以前想要做二维码扫描,只能通过第三方ZBar与ZXing. ZBar在扫描的灵敏度上,和内存的使用上相对于ZXing上都是较优的,但是对于 “圆角二维码” 的扫描确很困 ...
- ipad开发:二维码扫描,摄像头旋转角度问题解决办法
之前一直是在手机上开发,用系统原生二维码扫描功能,一点问题都没有,但是在ipad上,用户是横屏操作的,虽然界面旋转了,是横屏的,但是摄像头里显示的依然是竖屏效果,也就是说从摄像头里看到的和人眼看到的内 ...
随机推荐
- Office 2010 SP2简体中文正式版下载
此次发布的SP2包含最新的更新,提高安全性.性能和稳定性,此外SP2还是之前发布的所有更新.累积性更新的汇总.SP2还改善了Office 2010与IE10.Windows 8.Windows Ser ...
- [原]基于CAS实现单点登录(SSO):cas client端的退出问题
自从CAS 3.4就很好的支持了单点注销功能,配置也很简单. 之前版本因为在CAS服务器通过HttpClient发送消息时并未指定为POST方式,所以在CAS客户端的注销Filter中没有收到POST ...
- vagrant打造自己的开发环境
vagrant打造自己的开发环境 缘由: 在网上看到斌哥,爽神都写了关于vagrant的博客,都在说很强大,所以很好奇这玩意怎么个强大,然后也就自己来一发玩玩看看. 真实缘由: 说实话是电脑配置太低, ...
- oracle导入导出exp,imp
exp dadifilm/oracle@dg file=/tmp/dadi.dmp full=y imp u_data/321@dg1 file=/dadi_desc.dmp Import: Rel ...
- mysql 语句练习
一. 设有一数据库,包括四个表:学生表(Student).课程表(Course).成绩表(Score)以及教师信息表(Teacher).四个表的结构分别如表1-1的表(一)~表( ...
- express手工实现session原理
var express = require('express'); var cookieParser = require('cookie-parser'); var bodyParser = requ ...
- 解析nodejs微信开发-2获取ticket
获取ticket是需要拼接url,url中需要获得的tocken 1.先判断有无tocken:若有则拼接url: 2.请求url: a.处理回调数据,注意时间戳和签名处理方式,此两项并未存到ticke ...
- 使用border-image实现类似iOS7的1px底边
使用border-image实现类似iOS7的1px底边 iOS7已经发布有一段时间,扁平化设计风格有很多值得称赞的地方,其中有很多设计细节都是值得研究的. 首先,来看下面iOS设置的截图中的bord ...
- 利用虚拟光驱实现 将WINDOWS文件供虚拟机中的UBUNTU共享
此方法只能实现(至少目前我发现只能这样)将文件传递给虚拟机中的ubuntu 中,供ubuntu系统阅读,拷贝等,但不能将ubuntu中的数据传递给windows. 即:每次更新windows的数据到u ...
- Struts2.x教程(一) Struts2介绍
一.Struts2是什么 Struts2是在WebWork2基础发展而来的.和Struts1一样, Struts2也是基于MVC的web层框架. 那么既然有了Struts1,为何还要Struts2? ...