項(xiàng)目需求要是用到二維碼掃描稿黄,這次使用的是AVFoundation框架實(shí)現(xiàn)唱星。相對(duì)于ZBar和ZXing效率更高(其次這兩個(gè)庫(kù)貌似也沒(méi)有人維護(hù)了)鞭缭、而且現(xiàn)在好多app也只都支持iOS7.0及以上系統(tǒng)。
Demo地址:
github地址
效果圖
IMG_1352.PNG
IMG_1353.PNG
好了現(xiàn)在就來(lái)說(shuō)說(shuō)怎么實(shí)現(xiàn)吧
1.定義一個(gè)類QRCodeReaderView類
#import <UIKit/UIKit.h>
@protocol QRCodeReaderViewDelegate <NSObject>
- (void)readerScanResult:(NSString *)result;
@end
@interface QRCodeReaderView : UIView
@property (nonatomic, weak)id<QRCodeReaderViewDelegate> delegate;
@property (nonatomic,copy)UIImageView * readLineView;
@property (nonatomic,assign)BOOL is_Anmotion;
@property (nonatomic,assign)BOOL is_AnmotionFinished;
//開(kāi)啟關(guān)閉掃描
- (void)start;
- (void)stop;
- (void)loopDrawLine;//初始化掃描線
@end
2.看看.m的實(shí)現(xiàn)
#import "QRCodeReaderView.h"
#import <AVFoundation/AVFoundation.h>
#define DeviceMaxHeight ([UIScreen mainScreen].bounds.size.height)
#define DeviceMaxWidth ([UIScreen mainScreen].bounds.size.width)
#define widthRate DeviceMaxWidth/320
#define contentTitleColorStr @"666666" //正文顏色較深
@interface QRCodeReaderView () <AVCaptureMetadataOutputObjectsDelegate>
{
//采集流
AVCaptureSession * session;
NSTimer * countTime;
}
@property (nonatomic, strong) CAShapeLayer *overlay;
@end
@implementation QRCodeReaderView
- (id)initWithFrame:(CGRect)frame
{
if ((self = [super initWithFrame:frame])) {
//初始化
[self instanceDevice];
}
return self;
}
初始化并創(chuàng)建
- (void)instanceDevice
{
//掃描區(qū)域
UIImage *hbImage=[UIImage imageNamed:@"scanscanBg"];
UIImageView * scanZomeBack=[[UIImageView alloc] init];
scanZomeBack.backgroundColor = [UIColor clearColor];
scanZomeBack.layer.borderColor = [UIColor whiteColor].CGColor;
scanZomeBack.layer.borderWidth = 2.5;
scanZomeBack.image = hbImage;
//添加一個(gè)背景圖片
CGRect mImagerect = CGRectMake(60*widthRate, (DeviceMaxHeight-200*widthRate)/2, 200*widthRate, 200*widthRate);
[scanZomeBack setFrame:mImagerect];
CGRect scanCrop=[self getScanCrop:mImagerect readerViewBounds:self.frame];
[self addSubview:scanZomeBack];
//獲取攝像設(shè)備
AVCaptureDevice * device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
//創(chuàng)建輸入流
AVCaptureDeviceInput * input = [AVCaptureDeviceInput deviceInputWithDevice:device error:nil];
//創(chuàng)建輸出流
AVCaptureMetadataOutput * output = [[AVCaptureMetadataOutput alloc]init];
//設(shè)置代理 在主線程里刷新
[output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
output.rectOfInterest = scanCrop;
//初始化鏈接對(duì)象
session = [[AVCaptureSession alloc]init];
//高質(zhì)量采集率
[session setSessionPreset:AVCaptureSessionPresetHigh];
if (input) {
[session addInput:input];
}
if (output) {
[session addOutput:output];
//設(shè)置掃碼支持的編碼格式(如下設(shè)置條形碼和二維碼兼容)
NSMutableArray *a = [[NSMutableArray alloc] init];
if ([output.availableMetadataObjectTypes containsObject:AVMetadataObjectTypeQRCode]) {
[a addObject:AVMetadataObjectTypeQRCode];
}
if ([output.availableMetadataObjectTypes containsObject:AVMetadataObjectTypeEAN13Code]) {
[a addObject:AVMetadataObjectTypeEAN13Code];
}
if ([output.availableMetadataObjectTypes containsObject:AVMetadataObjectTypeEAN8Code]) {
[a addObject:AVMetadataObjectTypeEAN8Code];
}
if ([output.availableMetadataObjectTypes containsObject:AVMetadataObjectTypeCode128Code]) {
[a addObject:AVMetadataObjectTypeCode128Code];
}
output.metadataObjectTypes=a;
}
AVCaptureVideoPreviewLayer * layer = [AVCaptureVideoPreviewLayer layerWithSession:session];
layer.videoGravity=AVLayerVideoGravityResizeAspectFill;
layer.frame=self.layer.bounds;
[self.layer insertSublayer:layer atIndex:0];
[self setOverlayPickerView:self];
//開(kāi)始捕獲
[session startRunning];
}
掃描線條
-(void)loopDrawLine
{
_is_AnmotionFinished = NO;
CGRect rect = CGRectMake(60*widthRate, (DeviceMaxHeight-200*widthRate)/2, 200*widthRate, 2);
if (_readLineView) {
_readLineView.alpha = 1;
_readLineView.frame = rect;
}
else{
_readLineView = [[UIImageView alloc] initWithFrame:rect];
[_readLineView setImage:[UIImage imageNamed:@"scanLine"]];
[self addSubview:_readLineView];
}
[UIView animateWithDuration:1.5 animations:^{
//修改fream的代碼寫在這里
_readLineView.frame =CGRectMake(60*widthRate, (DeviceMaxHeight-200*widthRate)/2+200*widthRate-5, 200*widthRate, 2);
} completion:^(BOOL finished) {
if (!_is_Anmotion) {
[self loopDrawLine];
}
_is_AnmotionFinished = YES;
}];
}
- (void)setOverlayPickerView:(QRCodeReaderView *)reader
{
CGFloat wid = 60*widthRate;
CGFloat heih = (DeviceMaxHeight-200*widthRate)/2;
//最上部view
CGFloat alpha = 0.6;
UIView* upView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, DeviceMaxWidth, heih)];
upView.alpha = alpha;
upView.backgroundColor = [self colorFromHexRGB:contentTitleColorStr];
[reader addSubview:upView];
//用于說(shuō)明的label
UILabel * labIntroudction= [[UILabel alloc] init];
labIntroudction.backgroundColor = [UIColor clearColor];
labIntroudction.frame=CGRectMake(0, 64+(heih-64-50*widthRate)/2, DeviceMaxWidth, 50*widthRate);
labIntroudction.textAlignment = NSTextAlignmentCenter;
labIntroudction.textColor=[UIColor whiteColor];
labIntroudction.text=@"將二維碼放入框中魏颓,即自動(dòng)掃描";
[upView addSubview:labIntroudction];
//左側(cè)的view
UIView * cLeftView = [[UIView alloc] initWithFrame:CGRectMake(0, heih, wid, 200*widthRate)];
cLeftView.alpha = alpha;
cLeftView.backgroundColor = [self colorFromHexRGB:contentTitleColorStr];
[reader addSubview:cLeftView];
//右側(cè)的view
UIView *rightView = [[UIView alloc] initWithFrame:CGRectMake(DeviceMaxWidth-wid, heih, wid, 200*widthRate)];
rightView.alpha = alpha;
rightView.backgroundColor = [self colorFromHexRGB:contentTitleColorStr];
[reader addSubview:rightView];
//底部view
UIView * downView = [[UIView alloc] initWithFrame:CGRectMake(0, heih+200*widthRate, DeviceMaxWidth, DeviceMaxHeight - heih-200*widthRate)];
downView.alpha = alpha;
downView.backgroundColor = [self colorFromHexRGB:contentTitleColorStr];
[reader addSubview:downView];
- (void)turnBtnEvent:(UIButton *)button_
{
button_.selected = !button_.selected;
if (button_.selected) {
[self turnTorchOn:YES];
}
else{
[self turnTorchOn:NO];
}
}
掃描區(qū)域
-(CGRect)getScanCrop:(CGRect)rect readerViewBounds: (CGRect)readerViewBounds
{
CGFloat x,y,width,height;
x = (CGRectGetHeight(readerViewBounds)-CGRectGetHeight(rect))/2/CGRectGetHeight(readerViewBounds);
y = (CGRectGetWidth(readerViewBounds)-CGRectGetWidth(rect))/2/CGRectGetWidth(readerViewBounds);
width = CGRectGetHeight(rect)/CGRectGetHeight(readerViewBounds);
height = CGRectGetWidth(rect)/CGRectGetWidth(readerViewBounds);
return CGRectMake(x, y, width, height);
}
開(kāi)始掃描
- (void)start
{
[session startRunning];
}
停止掃描
- (void)stop
{
[session stopRunning];
}
掃描結(jié)果
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection
{
if (metadataObjects && metadataObjects.count>0) {
AVMetadataMachineReadableCodeObject * metadataObject = [metadataObjects objectAtIndex : 0 ];
//輸出掃描字符串
if (_delegate && [_delegate respondsToSelector:@selector(readerScanResult:)]) {
[_delegate readerScanResult:metadataObject.stringValue];
}
}