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

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

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

  UI效果如图

  IBOutlet、IBAction如下:

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

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

  二、控制器ViewController.h

  首先导入AVFoundation框架

  1. #import <AVFoundation/AVFoundation.h>

  然后控制器实现AVCaptureMetadataOutputObjectsDelegate协议

  1. @interface ViewController ()<AVCaptureMetadataOutputObjectsDelegate>

  整体property如下:

  1. @property (strong, nonatomic) UIView *boxView;
  2. @property (nonatomic) BOOL isReading;
  3. @property (strong, nonatomic) CALayer *scanLayer;
  4.  
  5. -(BOOL)startReading;
  6. -(void)stopReading;
  7.  
  8. //捕捉会话
  9. @property (nonatomic, strong) AVCaptureSession *captureSession;
  10. //展示layer
  11. @property (nonatomic, strong) AVCaptureVideoPreviewLayer *videoPreviewLayer;

  然后在ViewDidLoad方法中初始化

  1. - (void)viewDidLoad {
  2. [super viewDidLoad];
  3.  
  4. _captureSession = nil;
  5. _isReading = NO;
  6.  
  7. }

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

  1. - (BOOL)startReading {
  2. NSError *error;
  3.  
  4. //1.初始化捕捉设备(AVCaptureDevice),类型为AVMediaTypeVideo
  5. AVCaptureDevice *captureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
  6.  
  7. //2.用captureDevice创建输入流
  8. AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:captureDevice error:&error];
  9. if (!input) {
  10. NSLog(@"%@", [error localizedDescription]);
  11. return NO;
  12. }
  13.  
  14. //3.创建媒体数据输出流
  15. AVCaptureMetadataOutput *captureMetadataOutput = [[AVCaptureMetadataOutput alloc] init];
  16.  
  17. //4.实例化捕捉会话
  18. _captureSession = [[AVCaptureSession alloc] init];
  19.  
  20. //4.1.将输入流添加到会话
  21. [_captureSession addInput:input];
  22.  
  23. //4.2.将媒体输出流添加到会话中
  24. [_captureSession addOutput:captureMetadataOutput];
  25.  
  26. //5.创建串行队列,并加媒体输出流添加到队列当中
  27. dispatch_queue_t dispatchQueue;
  28. dispatchQueue = dispatch_queue_create("myQueue", NULL);
  29. //5.1.设置代理
  30. [captureMetadataOutput setMetadataObjectsDelegate:self queue:dispatchQueue];
  31.  
  32. //5.2.设置输出媒体数据类型为QRCode
  33. [captureMetadataOutput setMetadataObjectTypes:[NSArray arrayWithObject:AVMetadataObjectTypeQRCode]];
  34.  
  35. //6.实例化预览图层
  36. _videoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:_captureSession];
  37.  
  38. //7.设置预览图层填充方式
  39. [_videoPreviewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];
  40.  
  41. //8.设置图层的frame
  42. [_videoPreviewLayer setFrame:_viewPreview.layer.bounds];
  43.  
  44. //9.将图层添加到预览view的图层上
  45. [_viewPreview.layer addSublayer:_videoPreviewLayer];
  46.  
  47. //10.设置扫描范围
  48. captureMetadataOutput.rectOfInterest = CGRectMake(0.2f, 0.2f, 0.8f, 0.8f);
  49.  
  50. //10.1.扫描框
  51. _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)];
  52. _boxView.layer.borderColor = [UIColor greenColor].CGColor;
  53. _boxView.layer.borderWidth = 1.0f;
  54.  
  55. [_viewPreview addSubview:_boxView];
  56.  
  57. //10.2.扫描线
  58. _scanLayer = [[CALayer alloc] init];
  59. _scanLayer.frame = CGRectMake(, , _boxView.bounds.size.width, );
  60. _scanLayer.backgroundColor = [UIColor brownColor].CGColor;
  61.  
  62. [_boxView.layer addSublayer:_scanLayer];
  63.  
  64. NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:0.2f target:self selector:@selector(moveScanLayer:) userInfo:nil repeats:YES];
  65. [timer fire];
  66. //10.开始扫描
  67. [_captureSession startRunning];
  68. return YES;
  69. }

  实现AVCaptureMetadataOutputObjectsDelegate协议方法

  1. #pragma mark - AVCaptureMetadataOutputObjectsDelegate
  2. - (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection
  3. {
  4. //判断是否有数据
  5. if (metadataObjects != nil && [metadataObjects count] > ) {
  6. AVMetadataMachineReadableCodeObject *metadataObj = [metadataObjects objectAtIndex:];
  7. //判断回传的数据类型
  8. if ([[metadataObj type] isEqualToString:AVMetadataObjectTypeQRCode]) {
  9. [_lblStatus performSelectorOnMainThread:@selector(setText:) withObject:[metadataObj stringValue] waitUntilDone:NO];
  10.  
  11. [self performSelectorOnMainThread:@selector(stopReading) withObject:nil waitUntilDone:NO];
  12. _isReading = NO;
  13. }
  14. }
  15. }

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

  1. - (void)moveScanLayer:(NSTimer *)timer
  2. {
  3. CGRect frame = _scanLayer.frame;
  4. if (_boxView.frame.size.height < _scanLayer.frame.origin.y) {
  5. frame.origin.y = ;
  6. _scanLayer.frame = frame;
  7. }else{
  8.  
  9. frame.origin.y += ;
  10.  
  11. [UIView animateWithDuration:0.1 animations:^{
  12. _scanLayer.frame = frame;
  13. }];
  14. }
  15. }

  实现开始和停止方法

  1. - (IBAction)startStopReading:(id)sender {
  2. if (!_isReading) {
  3. if ([self startReading]) {
  4. [_startBtn setTitle:@"Stop" forState:UIControlStateNormal];
  5. [_lblStatus setText:@"Scanning for QR Code"];
  6. }
  7. }
  8. else{
  9. [self stopReading];
  10. [_startBtn setTitle:@"Start!" forState:UIControlStateNormal];
  11. }
  12.  
  13. _isReading = !_isReading;
  14. }
  15.  
  16. -(void)stopReading{
  17. [_captureSession stopRunning];
  18. _captureSession = nil;
  19. [_scanLayer removeFromSuperlayer];
  20. [_videoPreviewLayer removeFromSuperlayer];
  21. }

  大功告成

  示例源码地址: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. Office 2010 SP2简体中文正式版下载

    此次发布的SP2包含最新的更新,提高安全性.性能和稳定性,此外SP2还是之前发布的所有更新.累积性更新的汇总.SP2还改善了Office 2010与IE10.Windows 8.Windows Ser ...

  2. [原]基于CAS实现单点登录(SSO):cas client端的退出问题

    自从CAS 3.4就很好的支持了单点注销功能,配置也很简单. 之前版本因为在CAS服务器通过HttpClient发送消息时并未指定为POST方式,所以在CAS客户端的注销Filter中没有收到POST ...

  3. vagrant打造自己的开发环境

    vagrant打造自己的开发环境 缘由: 在网上看到斌哥,爽神都写了关于vagrant的博客,都在说很强大,所以很好奇这玩意怎么个强大,然后也就自己来一发玩玩看看. 真实缘由: 说实话是电脑配置太低, ...

  4. oracle导入导出exp,imp

    exp dadifilm/oracle@dg file=/tmp/dadi.dmp full=y imp u_data/321@dg1  file=/dadi_desc.dmp Import: Rel ...

  5. mysql 语句练习

    一.            设有一数据库,包括四个表:学生表(Student).课程表(Course).成绩表(Score)以及教师信息表(Teacher).四个表的结构分别如表1-1的表(一)~表( ...

  6. express手工实现session原理

    var express = require('express'); var cookieParser = require('cookie-parser'); var bodyParser = requ ...

  7. 解析nodejs微信开发-2获取ticket

    获取ticket是需要拼接url,url中需要获得的tocken 1.先判断有无tocken:若有则拼接url: 2.请求url: a.处理回调数据,注意时间戳和签名处理方式,此两项并未存到ticke ...

  8. 使用border-image实现类似iOS7的1px底边

    使用border-image实现类似iOS7的1px底边 iOS7已经发布有一段时间,扁平化设计风格有很多值得称赞的地方,其中有很多设计细节都是值得研究的. 首先,来看下面iOS设置的截图中的bord ...

  9. 利用虚拟光驱实现 将WINDOWS文件供虚拟机中的UBUNTU共享

    此方法只能实现(至少目前我发现只能这样)将文件传递给虚拟机中的ubuntu 中,供ubuntu系统阅读,拷贝等,但不能将ubuntu中的数据传递给windows. 即:每次更新windows的数据到u ...

  10. Struts2.x教程(一) Struts2介绍

    一.Struts2是什么 Struts2是在WebWork2基础发展而来的.和Struts1一样, Struts2也是基于MVC的web层框架. 那么既然有了Struts1,为何还要Struts2? ...