原生的二维码
第一步:添加代理<AVCaptureMetadataOutputObjectsDelegate>
第二步:完整代码;
{
NSTimer
*timer;
}
//1.初始化捕捉设备(AVCaptureDevice),类型为AVMediaTypeVideo
@property (strong,
nonatomic)
AVCaptureDevice *captureDevice;
//2.用captureDevice创建输入流
@property
(strong,
nonatomic)
AVCaptureDeviceInput *input;
//3.创建媒体数据输出流
@property
(strong,
nonatomic)
AVCaptureMetadataOutput *output;
//捕捉会话
@property
(strong,
nonatomic)
AVCaptureSession *session;
//展示layer
@property
(
strong,
nonatomic)
AVCaptureVideoPreviewLayer *previewLayer;
//处理
@property (strong,
nonatomic)
UIView
*boxView;//扫描框
@property (strong,
nonatomic)
CALayer *scanLayer;//运动的线
@property
(strong,
nonatomic)
UIView
*viewPreview;//展示layer层
@end
@implementation
QrCodeController
#pragma mark - get
#pragma mark -初始化捕捉设备
- (AVCaptureDevice *)captureDevice{
if (!_captureDevice)
{
_captureDevice = [AVCaptureDevice
defaultDeviceWithMediaType:AVMediaTypeVideo];
}
return
_captureDevice;
}
#pragma mark -创建输入流
- (AVCaptureDeviceInput *)input{
if (!_input)
{
_input = [AVCaptureDeviceInput
deviceInputWithDevice:self.captureDevice
error:nil];
}
return
_input;
}
/*
*AVCaptureMetadataOutput
中的属性rectOfInterest
看起来是CGRect类型,
实际上是填写一个比例。加入屏幕的frame
为 x , y, w, h,
要设置的扫描区域的frame
为 x1, y1, w1, h1.
那么rectOfInterest
应该设置为 CGRectMake(y1/x, x1/y, h1/h, w1/w)。
*
*/
#pragma mark -创建媒体数据输出流
- (AVCaptureMetadataOutput *)output{
if (!_output)
{
_output = [[AVCaptureMetadataOutput
alloc]
init];
CGRect viewFrame =
self.viewPreview.frame;
CGRect boxFrame =
self.boxView.frame;
CGFloat x = boxFrame.origin.y/viewFrame.origin.x;
CGFloat y = boxFrame.origin.x/viewFrame.origin.y;
CGFloat width = boxFrame.size.height/viewFrame.size.height;
CGFloat height = boxFrame.size.width/viewFrame.size.width;
_output.rectOfInterest
= CGRectMake(x, y, width, height);
}
return
_output;
}
#pragma mark -捕捉会话
- (AVCaptureSession *)session{
if (!_session)
{
_session = [[AVCaptureSession
alloc]
init];
}
return
_session;
}
#pragma mark -实例化预览图层
- (AVCaptureVideoPreviewLayer *)previewLayer
{
if (!_previewLayer)
{
_previewLayer = [AVCaptureVideoPreviewLayer
layerWithSession:self.session];
//设置预览图层填充方式
[_previewLayer
setVideoGravity:AVLayerVideoGravityResizeAspectFill];
}
return
_previewLayer;
}
#pragma mark -预览层
- (UIView *)viewPreview{
if (!_viewPreview)
{
_viewPreview = [[UIView
alloc]initWithFrame:CGRectMake(0,
NavBarHeight,
SCREEN_WIDTH,
SCREEN_HEIGHT -
NavBarHeight)];
_viewPreview.backgroundColor
= [UIColor
blueColor];
}
return
_viewPreview;
}
#pragma mark -扫描框
- (UIView *)boxView{
if (!_boxView){
_boxView = [[UIView
alloc]initWithFrame:CGRectMake(50,
100,
SCREEN_WIDTH -
100,
240)];
_boxView.layer.masksToBounds
= YES;
_boxView.layer.borderColor
= [UIColor
greenColor].CGColor;
_boxView.layer.borderWidth
= 1;
}
return
_boxView;
}
#pragma mark -扫描线
- (CALayer *)scanLayer{
if (!_scanLayer)
{
_scanLayer = [[CALayer
alloc]init];
_scanLayer .frame
= CGRectMake(0,
0,
self.boxView.bounds.size.width,
2);
_scanLayer.backgroundColor
= [UIColor
greenColor].CGColor;
}
return
_scanLayer;
}
- (void)viewDidLoad {
[super
viewDidLoad];
self.navBar.titleLabel.text
= @"二维码";
[self
startScaning];
// Do any additional setup after loading the view.
}
#pragma mark -开始扫描
- (void)startScaning{
// 1.判断输入能否添加到会话中
if (![self.session
canAddInput:self.input])
{
return;
}
[self.session
addInput:self.input];
// 2.判断输出能够添加到会话中
if (![self.session
canAddOutput:self.output])
{
return;
}
[self.session
addOutput:self.output];
// 3.设置监听监听输出解析到的数据
[self.output
setMetadataObjectsDelegate:self
queue:dispatch_get_main_queue()];
//4.设置输出媒体数据类型为QRCode
/*****************************************************
二维码和条形码要分开来写
如果是二维码
[captureMetadataOutput setMetadataObjectTypes:[NSArray arrayWithObject:AVMetadataObjectTypeQRCode]];
如果条形码
[captureMetadataOutput setMetadataObjectTypes:[NSArray arrayWithObjects:AVMetadataObjectTypeEAN13Code, AVMetadataObjectTypeEAN8Code, AVMetadataObjectTypeCode128Code, nil]];
*/
[self.output
setMetadataObjectTypes:[NSArray
arrayWithObject:AVMetadataObjectTypeQRCode]];
//5.预览层
[self.view
addSubview:self.viewPreview];
self.previewLayer.frame
= self.viewPreview.layer.bounds;
[self.viewPreview.layer
addSublayer:self.previewLayer];
//6.扫描框
[self.viewPreview
addSubview:self.boxView];
//7.扫描线
[self.boxView.layer
addSublayer:self.scanLayer];
timer = [NSTimer
scheduledTimerWithTimeInterval:0.2f
target:self
selector:@selector(moveScanLayer:)
userInfo:nil
repeats:YES];
[timer
fire];
//11.开始扫描
[self.session
startRunning];
}
-(void)stopReading
{
[_session
stopRunning];
_session =
nil;
if (timer.isValid)
{
[timer
invalidate];
timer=nil;
}
[_scanLayer
removeFromSuperlayer];
[_boxView
removeFromSuperview];
[_previewLayer
removeFromSuperlayer];
[_viewPreview
removeFromSuperview];
}
#pragma mark - AVCaptureMetadataOutputObjectsDelegate
- (void)captureOutput:(AVCaptureOutput
*)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection
*)connection
{
NSString *urlStr;
//判断是否有数据
if (metadataObjects !=
nil && [metadataObjects
count] >
0) {
AVMetadataMachineReadableCodeObject *metadataObj = [metadataObjects
objectAtIndex:0];
//判断回传的数据类型
if ([[metadataObj
type]
isEqualToString:AVMetadataObjectTypeQRCode])
{
urlStr = metadataObj.stringValue;
NSLog(@"%@",urlStr);
[self
performSelectorOnMainThread:@selector(stopReading)
withObject:nil
waitUntilDone:YES];
}
}
}
#pragma mark -
修改那条线的位置关系
- (void)moveScanLayer:(NSTimer
*)timer
{
CGRect frame =
_scanLayer.frame;
if (_boxView.frame.size.height
== _scanLayer.frame.origin.y)
{
frame.origin.y
= 0;
_scanLayer.frame
= frame;
}else{
frame.origin.y
+= 5;
if (frame.origin.y
> _boxView.frame.size.height)
{
frame.origin.y
= _boxView.frame.size.height;
}
[UIView
animateWithDuration:0.1
animations:^{
_scanLayer.frame
= frame;
}];
}
}
最后:运行效果: