iOS学习——iOS原生实现二维码扫描
最近项目上需要开发扫描二维码进行签到的功能,主要用于开会签到的场景,所以为了避免作弊,我们再开发时只采用直接扫描的方式,并且要屏蔽从相册读取图片,此外还在二维码扫描成功签到时后台会自动上传用户的当前地点,如何自动定位获取用户的当前地点在上一篇随笔iOS学习——自动定位中已经讲过了,本文就简单地说一下如何利用iOS原生的模块实现二维码的扫描。
二维码扫描是很多应用都会实现的功能,比较著名的第三方开源库是Google出品的ZXing,其的OC的移植版本是ZXingObjc。iOS系统原生的二维码扫描模块是在iOS7之后推出的,它主要是利用iOS设备的后置摄像头进行实现的。
要调用系统的摄像头识别二维码,我们需要导入系统的AVFoundation库。使用系统的摄像头,我们一般的需要以下五个对象:一个后置摄像头设备(AVCaptureDevice)、一个输入(AVCaptureDeviceInput)、一个输出(AVCaptureMetadataOutput)、一个协调控制器(AVCaptureSession)、一个预览层(AVCaptureVideoPreviewLayer),此外为了更好的体验效果,我们加入了缩放手势,在进行二维码扫描的时候可以手动进行缩放扫描区域,以获得更好的扫描效果。
@interface CJScanQRCodeViewController () <AVCaptureMetadataOutputObjectsDelegate> @property (strong, nonatomic) AVCaptureDevice * device; //捕获设备,默认后置摄像头
@property (strong, nonatomic) AVCaptureDeviceInput * input; //输入设备
@property (strong, nonatomic) AVCaptureMetadataOutput * output;//输出设备,需要指定他的输出类型及扫描范围
@property (strong, nonatomic) AVCaptureSession * session; //AVFoundation框架捕获类的中心枢纽,协调输入输出设备以获得数据
@property (strong, nonatomic) AVCaptureVideoPreviewLayer * previewLayer;//展示捕获图像的图层,是CALayer的子类 @property (strong, nonatomic) UIPinchGestureRecognizer *pinchGes;//缩放手势
@property (assign, nonatomic) CGFloat scanRegion_W;//二维码正方形扫描区域的宽度,根据不同机型适配 @end
首先,我们是需要进行对我们的一些设备进行配置,比喻需要用到自动定位,就需要对定位信息进行配置,接着对二维码扫描的相关设备进行配置,然后对我们的缩放手势进行设置,都配置完之后,直接开始启动二维码扫描就可以了,成功扫码并识别到信息时候会调用对应的 AVCaptureMetadataOutputObjectsDelegate 代理的 - (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection 方法进行后期处理,我们需要实现代理的该方法,在其中编写我们需要的功能逻辑。
- (void)viewDidLoad {
[super viewDidLoad];
//页面标题
self.title = @"扫一扫";
//配置定位信息
[self configLocation];
//配置二维码扫描
[self configBasicDevice];
//配置缩放手势
[self configPinchGes];
//开始启动
[self.session startRunning];
}
关于二维码扫描设备的配置流程,一般地,我们先将需要的五大设备进行初始化,然后需要进行对应的设置没具体的设置流程和方法见下面的代码和注释。
- (void)configBasicDevice{
//默认使用后置摄像头进行扫描,使用AVMediaTypeVideo表示视频
self.device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
//设备输入 初始化
self.input = [[AVCaptureDeviceInput alloc]initWithDevice:self.device error:nil];
//设备输出 初始化,并设置代理和回调,当设备扫描到数据时通过该代理输出队列,一般输出队列都设置为主队列,也是设置了回调方法执行所在的队列环境
self.output = [[AVCaptureMetadataOutput alloc]init];
[self.output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
//会话 初始化,通过 会话 连接设备的 输入 输出,并设置采样质量为 高
self.session = [[AVCaptureSession alloc]init];
[self.session setSessionPreset:AVCaptureSessionPresetHigh];
//会话添加设备的 输入 输出,建立连接
if ([self.session canAddInput:self.input]) {
[self.session addInput:self.input];
}
if ([self.session canAddOutput:self.output]) {
[self.session addOutput:self.output];
}
//指定设备的识别类型 这里只指定二维码识别这一种类型 AVMetadataObjectTypeQRCode
//指定识别类型这一步一定要在输出添加到会话之后,否则设备的课识别类型会为空,程序会出现崩溃
[self.output setMetadataObjectTypes:@[AVMetadataObjectTypeQRCode]];
//设置扫描信息的识别区域,本文设置正中央的一块正方形区域,该区域宽度是scanRegion_W
//这里考虑了导航栏的高度,所以计算有点麻烦,识别区域越小识别效率越高,所以不设置整个屏幕
CGFloat navH = self.navigationController.navigationBar.bounds.size.height;
CGFloat viewH = ZYAppHeight - navH;
CGFloat scanViewH = self.scanRegion_W;
[self.output setRectOfInterest:CGRectMake((ZYAppWidth-scanViewH)/(*ZYAppWidth), (viewH-scanViewH)/(*viewH), scanViewH/ZYAppWidth, scanViewH/viewH)];
//预览层 初始化,self.session负责驱动input进行信息的采集,layer负责把图像渲染显示
//预览层的区域设置为整个屏幕,这样可以方便我们进行移动二维码到扫描区域,在上面我们已经对我们的扫描区域进行了相应的设置
self.previewLayer = [[AVCaptureVideoPreviewLayer alloc]initWithSession:self.session];
self.previewLayer.frame = CGRectMake(, , ZYAppWidth, ZYAppHeight);
self.previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
[self.view.layer addSublayer:self.previewLayer];
//扫描框 和扫描线的布局和设置,模拟正在扫描的过程,这一块加不加不影响我们的效果,只是起一个直观的作用
TNWCameraScanView *clearView = [[TNWCameraScanView alloc]initWithFrame:self.view.frame navH:navH];
[self.view addSubview:clearView];
//扫描框下面的信息label布局
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(, (viewH+scanViewH)/+10.0f, ZYAppWidth, 20.0f)];
label.text = @"扫一扫功能仅用于会议签到";
label.font = FONT(15.0f);
label.textColor = [UIColor whiteColor];
label.textAlignment = NSTextAlignmentCenter;
[self.view addSubview:label];
}
接下来我们看一下如何配置我们的缩放手势,这个相对而言就很简单了,我们直接在self.view上添加一个缩放手势,并在对应的方法中对我们的相机设备的焦距进行修改就达到了缩放的目的。
- (void)configPinchGes{
self.pinchGes = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(pinchDetected:)];
[self.view addGestureRecognizer:self.pinchGes];
} - (void)pinchDetected:(UIPinchGestureRecognizer*)recogniser{
if (!_device){
return;
}
//对手势的状态进行判断
if (recogniser.state == UIGestureRecognizerStateBegan){
_initScale = _device.videoZoomFactor;
}
//相机设备在改变某些参数前必须先锁定,直到改变结束才能解锁
NSError *error = nil;
[_device lockForConfiguration:&error]; //锁定相机设备
if (!error) {
CGFloat zoomFactor; //缩放因子
CGFloat scale = recogniser.scale;
if (scale < 1.0f) {
zoomFactor = self.initScale - pow(self.device.activeFormat.videoMaxZoomFactor, 1.0f - recogniser.scale);
} else {
zoomFactor = self.initScale + pow(self.device.activeFormat.videoMaxZoomFactor, (recogniser.scale - 1.0f) / 2.0f);
}
zoomFactor = MIN(15.0f, zoomFactor);
zoomFactor = MAX(1.0f, zoomFactor);
_device.videoZoomFactor = zoomFactor;
[_device unlockForConfiguration];
}
}
最后,我们需要重写代理的回调方法,实现我们在成功识别二维码之后要实现的功能逻辑。这样我们的二维码扫描功能就完成了。
#pragma mark - AVCaptureMetadataOutputObjectsDelegate
//后置摄像头扫描到二维码的信息
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection{
[self.session stopRunning]; //停止扫描
if ([metadataObjects count] >= ) {
//数组中包含的都是AVMetadataMachineReadableCodeObject 类型的对象,该对象中包含解码后的数据
AVMetadataMachineReadableCodeObject *qrObject = [metadataObjects lastObject];
//拿到扫描内容在这里进行个性化处理
NSString *result = qrObject.stringValue;
//解析数据进行处理并实现相应的逻辑
//代码省略
}
iOS学习——iOS原生实现二维码扫描的更多相关文章
- iOS中 基于LBXScan库二维码扫描 韩俊强的博客
每日更新关注:http://weibo.com/hanjunqiang 新浪微博 首先声明这个二维码扫描是借助于zxing. 功能模块都完全封装好了,不过界面合你口味,直接使用就好,如果不合口味,后 ...
- iOS 简单易用的二维码扫描及生成二维码三方控件LFQRCode,可灵活自定义UI
一.扫码 扫描的控件是一个view,使用者只需贴在自己的控制器内即可.其他UI用户可在自己控制器随便添加.代码如下 - (void)viewDidLoad { [super viewDidLoad]; ...
- iOS开发-二维码扫描和应用跳转
iOS开发-二维码扫描和应用跳转 序言 前面我们已经调到过怎么制作二维码,在我们能够生成二维码之后,如何对二维码进行扫描呢? 在iOS7之前,大部分应用中使用的二维码扫描是第三方的扫描框架,例如Z ...
- iOS 自带二维码扫描功能的实现
自从iOS7以后中新增了二维码扫描功能.因此可以在不借助第三方类库的情况下简单的写出二维码的扫描功能: 原生的二维码扫描功能在AVFoundation框架下,所以在使用原生的二维码扫描功能时要先导入A ...
- iOS:原生二维码扫描
做iOS的二维码扫描,有两个第三方库可以选择,ZBar和ZXing.今天要介绍的是iOS7.0后AVFoundation框架提供的原生二维码扫描. 首先需要添加AVFoundation.framewo ...
- iOS原生实现二维码拉近放大
http://www.cocoachina.com/ios/20180416/23033.html 2018-04-16 15:34 编辑: yyuuzhu 分类:iOS开发 来源:程序鹅 8 300 ...
- iOS 原生二维码扫描和生成
代码地址如下:http://www.demodashi.com/demo/12551.html 一.效果预览: 功能描述:WSLNativeScanTool是在利用原生API的条件下封装的二维码扫描工 ...
- iOS 原生二维码扫描(可限制扫描区域)
篇文章的主要原因不是展示如何使用 AVFoundation 来进行二维码扫描,更主要的是限制扫描二维码的范围.(因为默认的是全屏扫描) 项目遇到扫描二维码的功能需求,这里我放弃了使用三方库,而采用了 ...
- 【转】 iOS 原生二维码扫描(可限制扫描区域)
在用 AVFoundation 完成扫码后,遇到2个问题: 1,如何限制扫描范围? 2.条形码如何扫描? 一位朋友的文章帮助了我,特地转来,可以帮到有需要的朋友. 原文:http://blog.csd ...
随机推荐
- zabbix-agent 启动不起来
遇到一个问题 zabbix-agent 一直启动不起来 查看Zabbix Agent日志文件才究其原因. tail /var/log/zabbix/zabbix_agentd.logzabbix_a ...
- Flask從入門到入土(二)——請求响应與Flask扩展
———————————————————————————————————————————————————————————— 一.程序和請求上下文 Flask從客戶端收到請求時,要讓視圖函數能訪問一些對象 ...
- JVM笔记6-垃圾回收概述
JVM进行垃圾回收时要考虑哪的问题如下: 1.如何判定对象为垃圾对象? 1.引用计数法:在对象中添加一个引用计数器,当有地方引用这个对象的时候,引用计数器的值就+1,引用失效的时候,计数器的值就-1, ...
- 源码编译安装Apache-附一键部署脚本
1.进入apache官网https://www.apache.org/,点击Download 2.如图选择 3.选择httpd 4.下载两个包,2.2为CentOS6使用,2.4为CentOS7使用 ...
- C语言中的sizeof函数总结
sizeof函数的结果: 变量:变量所占的字节数. ; printf( 数组:数组所占的字节数. ,,,,}; ] = {,,,,}; printf("size_arr1=%d\n" ...
- 使用BEM命名规范来组织CSS代码
BEM 是 Block(块) Element(元素) Modifier(修饰器)的简称 使用BEM规范来命名CSS,组织HTML中选择器的结构,利于CSS代码的维护,使得代码结构更清晰(弊端主要是名字 ...
- 基于LDA的Topic Model变形
转载于: 转:基于LDA的Topic Model变形 最近有想用LDA理论的变形来解决问题,调研中.... 基于LDA的Topic Model变形 基于LDA的Topic Model变形最近几年来,随 ...
- Java中的Calendar方法
/** * @Title:JavaDate.java * @Package:com.yhd.chart.model * @Description:Java中的Calendar总结 * @author: ...
- HighCharts之2D折线图
HighCharts之2D折线图 1.HighCharts之2D折线图源码 line.html: <!DOCTYPE html> <html> <head> < ...
- Java Web项目(Extjs)报错四
1.Java Web项目(Extjs)报错四 具体报错如下: usage: java org.apache.catalina.startup.Catalina [ -config {pathname} ...