iOS中 扫描二维码/生成二维码详解

最近大家总是问我有没有关于二维码的demo,为了满足大家的需求,特此研究了一番,希望能帮到大家!

每日更新关注:http://weibo.com/hanjunqiang  新浪微博

指示根视图:

[objc] view plain copy

  1. self.window.rootViewController = [[UINavigationController alloc]initWithRootViewController:[SecondViewController new]];  

每日更新关注:http://weibo.com/hanjunqiang  新浪微博

生成二维码:

[objc] view plain copy

  1. //  Created by 韩俊强 on 15/11/27.  
  2. //  Copyright (c) 2015年 韩俊强. All rights reserved.  
  3. //  
  4.   
  5. #import "SecondViewController.h"  
  6.   
  7. @interface SecondViewController ()  
  8.   
  9. @property (nonatomic, strong) UITextField *tfCode;  
  10. @property (nonatomic, strong) UIButton *btnGenerate;  
  11. @property (nonatomic, strong) UIImageView *imageView;  
  12. @end  
  13.   
  14. @implementation SecondViewController  
  15.   
  16. - (void)viewDidLoad {  
  17.     [super viewDidLoad];  
  18.     CGSize windowSize = [UIScreen mainScreen].bounds.size;  
  19.       
  20.     self.tfCode = [[UITextField alloc] initWithFrame:CGRectMake(10, 64, windowSize.width-100, 40)];  
  21.     [self.view addSubview:self.tfCode];  
  22.     self.tfCode.borderStyle = UITextBorderStyleRoundedRect;  
  23.       
  24.     self.btnGenerate = [[UIButton alloc] initWithFrame:CGRectMake(windowSize.width-100, 64, 90, 40)];  
  25.     [self.view addSubview:self.btnGenerate];  
  26.     [self.btnGenerate addTarget:self action:@selector(actionGenerate) forControlEvents:UIControlEventTouchUpInside];  
  27.     self.btnGenerate.backgroundColor = [UIColor lightGrayColor];  
  28.     [self.btnGenerate setTitle:@"生成" forState:UIControlStateNormal];  
  29.     [self.btnGenerate setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];  
  30.       
  31.     self.imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 300, 300)];  
  32.     [self.view addSubview:self.imageView];  
  33.     self.imageView.center = CGPointMake(windowSize.width/2, windowSize.height/2);  
  34.       
  35.     self.tfCode.text = @"http://www.baidu.com";  
  36. }  
  37. - (void)actionGenerate  
  38. {  
  39.     NSString *text = self.tfCode.text;  
  40.       
  41.     NSData *stringData = [text dataUsingEncoding: NSUTF8StringEncoding];  
  42.       
  43.     //生成  
  44.     CIFilter *qrFilter = [CIFilter filterWithName:@"CIQRCodeGenerator"];  
  45.     [qrFilter setValue:stringData forKey:@"inputMessage"];  
  46.     [qrFilter setValue:@"M" forKey:@"inputCorrectionLevel"];  
  47.       
  48.     UIColor *onColor = [UIColor blackColor];  
  49.     UIColor *offColor = [UIColor whiteColor];  
  50.       
  51.     //上色  
  52.     CIFilter *colorFilter = [CIFilter filterWithName:@"CIFalseColor" keysAndValues:@"inputImage",qrFilter.outputImage,@"inputColor0",[CIColor colorWithCGColor:onColor.CGColor],@"inputColor1",[CIColor colorWithCGColor:offColor.CGColor],nil];  
  53.       
  54.     CIImage *qrImage = colorFilter.outputImage;  
  55.       
  56.     //绘制  
  57.     CGSize size = CGSizeMake(300, 300);  
  58.     CGImageRef cgImage = [[CIContext contextWithOptions:nil] createCGImage:qrImage fromRect:qrImage.extent];  
  59.     UIGraphicsBeginImageContext(size);  
  60.     CGContextRef context = UIGraphicsGetCurrentContext();  
  61.     CGContextSetInterpolationQuality(context, kCGInterpolationNone);  
  62.     CGContextScaleCTM(context, 1.0, -1.0);  
  63.     CGContextDrawImage(context, CGContextGetClipBoundingBox(context), cgImage);  
  64.     UIImage *codeImage = UIGraphicsGetImageFromCurrentImageContext();  
  65.     UIGraphicsEndImageContext();  
  66.       
  67.     CGImageRelease(cgImage);  
  68.       
  69.     self.imageView.image = codeImage;  
  70. }  

扫描二维码:

[objc] view plain copy

  1. //  Created by 韩俊强 on 15/11/27.  
  2. //  Copyright (c) 2015年 韩俊强. All rights reserved.  
  3. //  
  4.   
  5. #import "RootViewController.h"  
  6. #import <AVFoundation/AVFoundation.h>  
  7.   
  8. @interface RootViewController ()<AVCaptureMetadataOutputObjectsDelegate,UIAlertViewDelegate>  
  9.   
  10. @property (nonatomic, strong) UIView *scanRectView;  
  11. // 硬件设备  
  12. @property (strong, nonatomic) AVCaptureDevice            *device;  
  13. //输入设备  
  14. @property (strong, nonatomic) AVCaptureDeviceInput       *input;  
  15. //输出设备  
  16. @property (strong, nonatomic) AVCaptureMetadataOutput    *output;  
  17. //桥梁.连接输入和输出设备,  
  18. @property (strong, nonatomic) AVCaptureSession           *session;  
  19. @property (strong, nonatomic) AVCaptureVideoPreviewLayer *preview;  
  20.   
  21. @end  
  22.   
  23. @implementation RootViewController  
  24.   
  25. - (void)viewDidLoad {  
  26.     [super viewDidLoad];  
  27.     CGSize windowSize = [UIScreen mainScreen].bounds.size;  
  28.       
  29.     CGSize scanSize = CGSizeMake(windowSize.width*3/4, windowSize.width*3/4);  
  30.     CGRect scanRect = CGRectMake((windowSize.width-scanSize.width)/2, (windowSize.height-scanSize.height)/2, scanSize.width, scanSize.height);  
  31.       
  32.     scanRect = CGRectMake(scanRect.origin.y/windowSize.height, scanRect.origin.x/windowSize.width, scanRect.size.height/windowSize.height,scanRect.size.width/windowSize.width);  
  33.       
  34.     self.device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];  
  35.       
  36.     self.input = [AVCaptureDeviceInput deviceInputWithDevice:self.device error:nil];  
  37.       
  38.     self.output = [[AVCaptureMetadataOutput alloc]init];  
  39.     [self.output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];  
  40.       
  41.     self.session = [[AVCaptureSession alloc]init];  
  42.     [self.session setSessionPreset:([UIScreen mainScreen].bounds.size.height<500)?AVCaptureSessionPreset640x480:AVCaptureSessionPresetHigh];  
  43.     [self.session addInput:self.input];  
  44.     [self.session addOutput:self.output];  
  45.     self.output.metadataObjectTypes=@[AVMetadataObjectTypeQRCode];  
  46.     self.output.rectOfInterest = scanRect;  
  47.       
  48.     self.preview = [AVCaptureVideoPreviewLayer layerWithSession:self.session];  
  49.     self.preview.videoGravity = AVLayerVideoGravityResizeAspectFill;  
  50.     self.preview.frame = [UIScreen mainScreen].bounds;  
  51.     [self.view.layer insertSublayer:self.preview atIndex:0];  
  52.       
  53.     self.scanRectView = [UIView new];  
  54.     [self.view addSubview:self.scanRectView];  
  55.     self.scanRectView.frame = CGRectMake(0, 0, scanSize.width, scanSize.height);  
  56.     self.scanRectView.center = CGPointMake(CGRectGetMidX([UIScreen mainScreen].bounds), CGRectGetMidY([UIScreen mainScreen].bounds));  
  57.     self.scanRectView.layer.borderColor = [UIColor redColor].CGColor;  
  58.     self.scanRectView.layer.borderWidth = 1;  
  59.       
  60.       
  61.     //开始捕获  
  62.     [self.session startRunning];  
  63.       
  64. }  
  65.   
  66.   
  67. - (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection  
  68. {  
  69.     if ( (metadataObjects.count==0) )  
  70.     {  
  71.         return;  
  72.     }  
  73.       
  74.     if (metadataObjects.count>0) {  
  75.           
  76.         [self.session stopRunning];  
  77.           
  78.         AVMetadataMachineReadableCodeObject *metadataObject = metadataObjects.firstObject;  
  79.         //输出扫描字符串  
  80.           
  81.         UIAlertView *alert = [[UIAlertView alloc] initWithTitle:metadataObject.stringValue message:@"" delegate:self cancelButtonTitle:@"ok" otherButtonTitles: nil nil];  
  82.           
  83.         [alert show];  
  84.     }  
  85. }  
  86.   
  87. - (void)alertView:(UIAlertView *)alertView willDismissWithButtonIndex:(NSInteger)buttonIndex  
  88. {  
  89.     [self.session startRunning];  
  90. }  

每日更新关注:http://weibo.com/hanjunqiang  新浪微博

最终效果:(由于扫描二维码无法展示效果,所以自己动手真机测试吧!)

每日更新关注:http://weibo.com/hanjunqiang  新浪微博

IOS7之前,开发者进行扫码编程时,一般会借助第三方库。常用的是ZBarSDK,IOS7之后,系统的AVMetadataObject类中,为我们提供了解析二维码的接口。经过测试,使用原生API扫描和处理的效率非常高,远远高于第三方库。

一、使用方法示例

官方提供的接口非常简单,代码如下:

?


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

@interface ViewController ()<AVCaptureMetadataOutputObjectsDelegate>//用于处理采集信息的代理

{

    AVCaptureSession * session;//输入输出的中间桥梁

}

@end

@implementation ViewController

 

- (void)viewDidLoad {

    [super viewDidLoad];

    // Do any additional setup after loading the view, typically from a nib.

    //获取摄像设备

    AVCaptureDevice * device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];

    //创建输入流

    AVCaptureDeviceInput * input = [AVCaptureDeviceInput deviceInputWithDevice:device error:nil];

    //创建输出流

    AVCaptureMetadataOutput * output = [[AVCaptureMetadataOutput alloc]init];

    //设置代理 在主线程里刷新

    [output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];

     

    //初始化链接对象

    session = [[AVCaptureSession alloc]init];

    //高质量采集率

    [session setSessionPreset:AVCaptureSessionPresetHigh];

     

    [session addInput:input];

    [session addOutput:output];

    //设置扫码支持的编码格式(如下设置条形码和二维码兼容)

    output.metadataObjectTypes=@[AVMetadataObjectTypeQRCode,AVMetadataObjectTypeEAN13Code, AVMetadataObjectTypeEAN8Code, AVMetadataObjectTypeCode128Code];

        

    AVCaptureVideoPreviewLayer * layer = [AVCaptureVideoPreviewLayer layerWithSession:session];

    layer.videoGravity=AVLayerVideoGravityResizeAspectFill;

    layer.frame=self.view.layer.bounds;

    [self.view.layer insertSublayer:layer atIndex:0];

    //开始捕获

    [session startRunning];

}

之后我们的UI上已经可以看到摄像头捕获的内容,只要实现代理中的方法,就可以完成二维码条形码的扫描:

?


1

2

3

4

5

6

7

8

-(void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection{

    if (metadataObjects.count>0) {

        //[session stopRunning];

        AVMetadataMachineReadableCodeObject * metadataObject = [metadataObjects objectAtIndex : 0 ];

        //输出扫描字符串

        NSLog(@"%@",metadataObject.stringValue);

    }

}

二、一些优化

通过上面的代码测试,我们可以发现系统的解析处理效率是相当的高,iOS官方提供的API也确实非常强大,然而,我们可以做进一步的优化,将效率更加提高:

首先,AVCaptureMetadataOutput类中有一个这样的属性(在IOS7.0之后可用):

@property(nonatomic) CGRect rectOfInterest;

这个属性大致意思就是告诉系统它需要注意的区域,大部分APP的扫码UI中都会有一个框,提醒你将条形码放入那个区域,这个属性的作用就在这里,它可以设置一个范围,只处理在这个范围内捕获到的图像的信息。如此一来,可想而知,我们代码的效率又会得到很大的提高,在使用这个属性的时候。需要几点注意:

1、这个CGRect参数和普通的Rect范围不太一样,它的四个值的范围都是0-1,表示比例。

2、经过测试发现,这个参数里面的x对应的恰恰是距离左上角的垂直距离,y对应的是距离左上角的水平距离。

3、宽度和高度设置的情况也是类似。

3、举个例子如果我们想让扫描的处理区域是屏幕的下半部分,我们这样设置

?


1

output.rectOfInterest=CGRectMake(0.5,0,0.5, 1);

具体apple为什么要设计成这样,或者是这个参数我的用法那里不对,还需要了解的朋友给个指导。

每日更新关注:http://weibo.com/hanjunqiang  新浪微博

原文地址:http://blog.csdn.net/qq_31810357/article/details/50442512

时间: 2024-09-17 04:12:30

iOS中 扫描二维码/生成二维码详解的相关文章

iOS中 视频直播功能-流媒体的使用(详解)韩俊强的CSDN博客

上一篇博客:(流媒体实现视频播放和下载功能):http://blog.csdn.net/qq_31810357/article/details/50574914 最近视频直播功能比较火,处于需求,研究了一番,根据分析决定使用流媒体实现,代码简单易懂,接下来看教程: 每日更新关注:http://weibo.com/hanjunqiang  新浪微博 简单介绍: HLS 协议 : >5M会被AppStore拒绝  服务器要求低   延迟高    多平台 RTMP 协议:  电视直播   PC端使用

ios中创建可以拖动的view原理和实现详解(含代码)

有时候我们会需要在界面上拖动view;uiview是继承于uiresponder的,所以可以响应触摸相关的事件. 重点是以下一组方法: - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event  - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event - (void)touchesEnded:(NSSet *)touches withEvent:(UI

iOS 二维码生成及扫码详解及实例代码_IOS

iOS二维码生成及扫码      现在越来越多的应用加入二维码相关的业务,在iOS开发市场上很多开发人员都在使用第三方的扫码与生成二维码的控件,个人认为此类的第三方控件识别度不高.最近正好整理新框架的事情,研究了一下.具体代码如下  生成二维码代码 /** * @author 半 饱, 15-12-18 * * @brief 生成二维码图片 * * @param code 生成二维码图片内容 * @param width 二维码图片宽度 * @param height 二维码图片高度 * * @

Android群英传笔记——第十二章:Android5.X 新特性详解,Material Design UI的新体验

Android群英传笔记--第十二章:Android5.X 新特性详解,Material Design UI的新体验 第十一章为什么不写,因为我很早之前就已经写过了,有需要的可以去看 Android高效率编码-第三方SDK详解系列(二)--Bmob后端云开发,实现登录注册,更改资料,修改密码,邮箱验证,上传,下载,推送消息,缩略图加载等功能 这一章很多,但是很有趣,也是这书的最后一章知识点了,我现在还在考虑要不要写这个拼图和2048的案例,在此之前,我们先来玩玩Android5.X的新特性吧!

iOS 泛型中nullable、null resettable、null kindof 用法详解_IOS

 iOS9新出的关键字:用来修饰属性,或者方法的参数,方法的返回值 iOS9新出关键字nonnull,nullable,null_resettable,_Null_unspecified 需要注意的一点只能修饰对象,不能修饰基本数据类型. 虽然在项目的代码编写中不会经常用到,不过在调用苹果系统方法的时候还是会经常遇到,需要做一个总结 nullable作用:表示可以为空 nullable书写规范: // 方式一: @property (nonatomic, strong, nullable) NS

c++中.dll与.lib文件的生成与使用的详解_C 语言

c++中.dll与.lib文件的生成与使用的详解 -------------------------------------------------------------------------------- 两种库: • 包含了函数所在的DLL文件和文件中函数位置的信息(入口),代码由运行时加载在进程空间中的DLL提供,称为动态链接库dynamic link library.• 包含函数代码本身,在编译时直接将代码加入程序当中,称为静态链接库static link library.共有两种链

iOS应用程序之间的几种跳转情况详解_IOS

前言 在iOS开发的过程中,我们经常会遇到比如需要从一个应用程序A跳转到另一个应用程序B的场景.这就需要我们掌握iOS应用程序之间的相互跳转知识.下面我们就常用到的几种跳转情况进行介绍. 一.跳转到另一个程序的主界面 每个程序都该有一个对应的Scheme,以确定对应的url 一个程序要跳转到(打开)另外一个程序,需要将另外一个程序的Scheme添加到自己的应用程序白名单中(在info.plist中配置:LSApplicationQueriesSchemes,类型为数组,在数组中添加相应的Sche

搭建Tomcat 8源码开发环境的步骤详解_Tomcat

前言 最近在网上搜索了很多关于tomcat源码环境搭建的文章,发现按照文章的步骤,几乎都启动不了,于是自己尝试搭建,下面是搭建的方法. 基础环境搭建 1.下载tomcat源代码,我这里是通过svn的方式下载的,svn下载地址 2.下载安装maven工具,这里我就不多说了,安装说明太多了,自己网上找. 3.IDE,我这里使用idea 生成maven工程 我的代码本地目录是: /Users/helanzhou/Documents/helanzhou/java/Tomcat/tomcat8/tomca

php源码 fsockopen获取网页内容实例详解_php实例

PHP fsockopen函数说明: Open Internet or Unix domain socket connection(打开套接字链接) Initiates a socket connection to the resource specified by target . fsockopen() returns a file pointer which may be used together with the other file functions (such as fgets(

最新最全PHP生成制作验证码代码详解(推荐)_php实例

1.0 首先先看代码 <?php header("Content-Type:text/html;Charset=UTF-");// 设置页面的编码风格 header("Content-Type:image/jpeg");// 通知浏览器输出的是jpeg格式的图像 $img = imagecreatetruecolor(,);//创建画布并设置大小 x轴 y轴 $bgcolor = imagecolorallocate($img, mt_rand(,), mt_