ios7 苹果原生二维码扫描

来源:转载

在ios7苹果推出了二维码扫描,以前想要做二维码扫描,只能通过第三方ZBar与ZXing。

ZBar在扫描的灵敏度上,和内存的使用上相对于ZXing上都是较优的,但是对于 “圆角二维码” 的扫描确很困难。

ZXing 是 Google Code上的一个开源的条形码扫描库,是用java设计的,连Google Glass 都在使用的。但有人为了追求更高效率以及可移植性,出现了c++ port. Github上的Objectivc-C port,其实就是用OC代码封装了一下而已,而且已经停止维护。这样效率非常低,在instrument下面可以看到CPU和内存疯涨,在内存小的机器上很容易崩溃。

AVFoundation无论在扫描灵敏度和性能上来说都是最优的。

首先要导入#import <AVFoundation/AVFoundation.h>框架

 

完成二维码扫描大致有十个步骤:

 // 1.获取输入设备 AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; // 2.创建输入对象 NSError *error; AVCaptureDeviceInput *inPut = [[AVCaptureDeviceInput alloc] initWithDevice:device error:&error]; if (inPut == nil) { UIAlertView *aler = [[UIAlertView alloc] initWithTitle:@"提示" message:@"设备不可用" delegate:nil cancelButtonTitle:nil otherButtonTitles:@"确定", nil]; [self.view addSubview:aler]; [aler show]; return; } // 3.创建输出对象 AVCaptureMetadataOutput *outPut = [[AVCaptureMetadataOutput alloc] init]; // 4.设置代理监听输出对象的输出流 (说明:使用主线程队列,相应比较同步,使用其他队列,相应不同步,容易让用户产生不好的体验) [outPut setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()]; // 5.创建会话 AVCaptureSession *session = [[AVCaptureSession alloc] init]; self.session = session; // 6.将输入和输出对象添加到会话 if ([session canAddInput:inPut]) { [session addInput:inPut]; } if ([session canAddOutput:outPut]) { [session addOutput:outPut]; } // 7.告诉输出对象, 需要输出什么样的数据 // 提示:一定要先设置会话的输出为output之后,再指定输出的元数据类型! [outPut setMetadataObjectTypes:@[AVMetadataObjectTypeQRCode]]; // 8.创建预览图层 AVCaptureVideoPreviewLayer *preViewLayer = [AVCaptureVideoPreviewLayer layerWithSession:session]; preViewLayer.frame = self.view.bounds; [self.view.layer insertSublayer:preViewLayer atIndex:0]; // 9.设置扫面范围 outPut.rectOfInterest = CGRectMake(0.2, 0.18, 0.6, 0.5); // 10.设置扫描框 UIView *boxView = [[UIView alloc] initWithFrame:CGRectMake(0.2 * SrceenW, 0.18 * SrceenH, 0.6 * SrceenW, 0.5 * SrceenH)]; self.boxView = boxView; boxView.layer.borderColor = [UIColor yellowColor].CGColor; boxView.layer.borderWidth = 3; [self.view addSubview:boxView]; // 设置扫描线 CALayer *scanLayer = [[CALayer alloc] init]; self.scanLayer = scanLayer; scanLayer.frame = CGRectMake(0, 0, boxView.bounds.size.width, 2); scanLayer.backgroundColor = [UIColor redColor].CGColor; [boxView.layer addSublayer:scanLayer]; // 开始扫描 [session startRunning];

其中第9个步骤是可以优化内存的

@property(nonatomic) CGRect rectOfInterest;

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

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

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

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

 

-----------------------------以下是源码:

#import "ScanQrcodeVController.h"

@protocol ScanQrcodeVControllerDelegate <NSObject>// 二维码返回结果-(void)scanQrcodeWithNString:(NSString *) ruselt;@[email protected] ScanQrcodeVController : [email protected] (nonatomic, weak) id<ScanQrcodeVControllerDelegate>delegate;@end

#import "ScanQrcodeVController.m"

@interface ScanQrcodeVController ()<AVCaptureMetadataOutputObjectsDelegate>// 会话@property (nonatomic, strong) AVCaptureSession *session;// 定时器@property (nonatomic, strong) CADisplayLink *link;// 扫描线@property (nonatomic, strong) CALayer *scanLayer;// 扫描框@property (nonatomic, weak) UIView *boxView;/// 保存二维码结果@property (nonatomic, copy) NSString *string;@[email protected] ScanQrcodeVController- (void)viewDidLoad { [super viewDidLoad]; self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"NavBack"] style:UIBarButtonItemStylePlain target:self action:@selector(goBack)]; self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"确定" style:UIBarButtonItemStylePlain target:self action:@selector(doneClick)]; [self scanCode]; }-(void)scanCode { CADisplayLink *link = [CADisplayLink displayLinkWithTarget:self selector:@selector(updataFrame)]; self.link = link; link.frameInterval = 3; [link addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes]; // 1.获取输入设备 AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; // 2.创建输入对象 NSError *error; AVCaptureDeviceInput *inPut = [[AVCaptureDeviceInput alloc] initWithDevice:device error:&error]; if (inPut == nil) { UIAlertView *aler = [[UIAlertView alloc] initWithTitle:@"提示" message:@"设备不可用" delegate:nil cancelButtonTitle:nil otherButtonTitles:@"确定", nil]; [self.view addSubview:aler]; [aler show]; return; } // 3.创建输出对象 AVCaptureMetadataOutput *outPut = [[AVCaptureMetadataOutput alloc] init]; // 4.设置代理监听输出对象的输出流 说明:使用主线程队列,相应比较同步,使用其他队列,相应不同步,容易让用户产生不好的体验 [outPut setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()]; // 5.创建会话 AVCaptureSession *session = [[AVCaptureSession alloc] init]; self.session = session; // 6.将输入和输出对象添加到会话 if ([session canAddInput:inPut]) { [session addInput:inPut]; } if ([session canAddOutput:outPut]) { [session addOutput:outPut]; } // 7.告诉输出对象, 需要输出什么样的数据 // 提示:一定要先设置会话的输出为output之后,再指定输出的元数据类型! [outPut setMetadataObjectTypes:@[AVMetadataObjectTypeQRCode]]; // 8.创建预览图层 AVCaptureVideoPreviewLayer *preViewLayer = [AVCaptureVideoPreviewLayer layerWithSession:session]; preViewLayer.frame = self.view.bounds; [self.view.layer insertSublayer:preViewLayer atIndex:0]; // 9.设置扫面范围 outPut.rectOfInterest = CGRectMake(0.2, 0.18, 0.6, 0.5); // 10.设置扫描框 UIView *boxView = [[UIView alloc] initWithFrame:CGRectMake(0.2 * SrceenW, 0.18 * SrceenH, 0.6 * SrceenW, 0.5 * SrceenH)]; self.boxView = boxView; boxView.layer.borderColor = [UIColor yellowColor].CGColor; boxView.layer.borderWidth = 3; [self.view addSubview:boxView]; // 设置扫描线 CALayer *scanLayer = [[CALayer alloc] init]; self.scanLayer = scanLayer; scanLayer.frame = CGRectMake(0, 0, boxView.bounds.size.width, 2); scanLayer.backgroundColor = [UIColor redColor].CGColor; [boxView.layer addSublayer:scanLayer]; // 开始扫描 [session startRunning];}-(void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection { if (metadataObjects.count > 0) { // 停止扫描 [self.session stopRunning]; // 移除CADisplayLink对象 [self.link removeFromRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes]; self.link = nil; // 取出数据 AVMetadataMachineReadableCodeObject *obj = [metadataObjects lastObject]; self.string = obj.stringValue; } NSLog(@"扫描--%@",self.string); [NSThread sleepForTimeInterval:1.0];}-(void)updataFrame { CGRect frame = self.scanLayer.frame; if (self.scanLayer.frame.origin.y > self.boxView.frame.size.height) { frame.origin.y = -20; self.scanLayer.frame = frame; }else{ frame.origin.y += 3; self.scanLayer.frame = frame; } }-(void)viewDidDisappear:(BOOL)animated{ [super viewDidDisappear:animated]; // 记得释放CADisplayLink对象 if (self.link != nil) { [self.link invalidate]; self.link = nil; }}// 返回上一个界面-(void)goBack { [self.navigationController popViewControllerAnimated:YES];}// 二维码扫描完成-(void)doneClick { // 设置代理 if ([self.delegate respondsToSelector:@selector(scanQrcodeWithNString:)]) { [self.delegate scanQrcodeWithNString:self.string]; } [self.navigationController popToRootViewControllerAnimated:YES];}@end

 

 

 

 

 

 

 



分享给朋友:
您可能感兴趣的文章:
随机阅读: