参考链接: http://www.jianshu.com/p/ad7827a8a0e6
实现二维码扫描中用到的类:
AVCaptureDevice : 获取设备的某项功能(二维码扫描中用到的是获取系统照相机的功能)
AVCaptureDeviceInput : 输入流 通过相机获取输入信息
AVCaptureSession : 建立一个完整的会话连接以进行扫描一个完整的会话连接包括输入以及输出 (该连接可以保证持续有效的输入和输出)
AVCaptureMetadataOutput : 输出流 在该类中设置输出信息的范围 以及输出信息的类型,该类需要设置代理以接收扫描到的有效信息,需要为输出流开辟一个新的线程以确保扫描结果的正常输出。
将输入流和输出流添加到会话连接,
AVCaptureVideoPreviewLayer : 预览类 通过该类查看扫描到的图像
实现部分:
在Build Phases Link Binary 中引入 AVFoundation框架
/*
在需要实现扫描功能的控制器中引入头文件
定义屏幕宽高
定义一个全局的静态变量(使用gcd创建子线程时使用)
同时该类要遵循输出流的代理协议
*/
#import <AVFoundation/AVFoundation.h>
#define Screen_Width [UIScreen mainScreen].bounds.size.width
#define Screen_Height [UIScreen mainScreen].bounds.size.height
static const char *qr_scan_queue = "qr_scan_queue"
@interface ViewController ()<AVCaptureMetadataOutputObjectsDelegate>
// 定义两个方法并在ViewDidLoad 中调用
- (void)viewDidLoad {
[super viewDidLoad];
[self declareScanFrame]; // 标识扫描区域
[self startScaning]; // 实现二维码扫描
}
-(void)declareScanFrame{
CALayer *layer = [[CALayer alloc]init];
layer.frame = CGRectMake(Screen_Width * 0.25,(Screen_Height - Screen_Width*0.5)/2 , Screen_Width*0.5, Screen_Width*0.5) ;
layer.backgroundColor = [UIColor clearColor].CGColor ;
layer.borderColor = [UIColor yellowColor].CGColor ;
layer.borderWidth = 1 ;
[self.view.layer addSublayer:layer] ;
}
-(void)startScaning{
/*
获取调用系统摄像机的功能
*/
AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo] ;
/*
建立输入
*/
NSError *error ;
AVCaptureDeviceInput *input = [[AVCaptureDeviceInput alloc]initWithDevice:device error:&error];
/*
建立输出
*/
AVCaptureMetadataOutput *output = [[AVCaptureMetadataOutput alloc]init];
output.rectOfInterest = CGRectMake(0.25, 0.25, 0.5,0.5);//设置扫描范围(输出范围)
dispatch_queue_t qr_queue = dispatch_queue_create(qr_scan_queue, NULL) ;
[output setMetadataObjectsDelegate:self queue:qr_queue] ; //设置输出代理
/*
建立一个数据传输的会话连接以维持持续扫描
*/
AVCaptureSession *session = [[AVCaptureSession alloc]init];
session.sessionPreset = AVCaptureSessionPreset1920x1080 ;
[session addInput:input];
[session addOutput:output];
[output setMetadataObjectTypes:[NSArray arrayWithObject:AVMetadataObjectTypeQRCode]] ; // 设置输出类型 只有输入类型为二维码时才会调用代理方法
// 预览类
AVCaptureVideoPreviewLayer *_layer = [[AVCaptureVideoPreviewLayer alloc]initWithSession:session];
[_layer setVideoGravity:AVLayerVideoGravityResizeAspectFill] ;
[_layer setFrame:self.view.frame] ;//视频窗口用来展示镜头捕获到的图像
[self.view.layer insertSublayer:_layer atIndex:0];
[session startRunning] ;//开始扫描
}
实现代理方法捕获输出
#pragma mark AVCaptureMetadataOutputObjectsDelegate
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection{
NSLog(@"获取到扫描数据%@",metadataObjects) ;
// 二维码的获取 捕获的数据由一个数组来管理 取数据时获取最新的一个数据
if (metadataObjects != nil && [metadataObjects count] > 0) {
AVMetadataMachineReadableCodeObject *metadataObj = [metadataObjects objectAtIndex:0];
NSString *result;
if ([[metadataObj type] isEqualToString:AVMetadataObjectTypeQRCode]) {
result = metadataObj.stringValue;
} else {
NSLog(@"不是二维码");
}
}
网友评论