欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

ios原生二维码扫描

程序员文章站 2022-03-23 13:10:43
做ios的二维码扫描,有两个第三方库可以选择,zbar和zxing。今天要介绍的是ios7.0后avfoundation框架提供的原生二维码扫描。 首先需要添加avfou...

做ios的二维码扫描,有两个第三方库可以选择,zbar和zxing。今天要介绍的是ios7.0后avfoundation框架提供的原生二维码扫描。

首先需要添加avfoundation.framework框架到你工程中build phase的"link binary with libraries"之下,然后就可以开始了。

一、做好准备工作,搭建ui

ui效果如图

iboutlet、ibaction如下:

@property (weak, nonatomic) iboutlet uiview *viewpreview;
@property (weak, nonatomic) iboutlet uilabel *lblstatus;
@property (weak, nonatomic) iboutlet uibutton *startbtn;
- (ibaction)startstopreading:(id)sender;

接下来就都是代码的事情了

二、控制器viewcontroller.h

首先导入avfoundation框架

#import <avfoundation/avfoundation.h>

然后控制器实现 avcapturemetadataoutputobjectsdelegate协议

@interface viewcontroller ()<avcapturemetadataoutputobjectsdelegate>

整体property如下:

@property (strong, nonatomic) uiview *boxview;
@property (nonatomic) bool isreading;
@property (strong, nonatomic) calayer *scanlayer;
-(bool)startreading;
-(void)stopreading;

//捕捉会话

@property (nonatomic, strong) avcapturesession *capturesession;

//展示layer

@property (nonatomic, strong) avcapturevideopreviewlayer *videopreviewlayer;

然后在viewdidload方法中初始化

- (void)viewdidload {
  [super viewdidload];

  _capturesession = nil;
   _isreading = no;
  
}

接下来实现startreading方法(这可就是重点咯)

- (bool)startreading {
 nserror *error;
 //1.初始化捕捉设备(avcapturedevice),类型为avmediatypevideo
 avcapturedevice *capturedevice = [avcapturedevice defaultdevicewithmediatype:avmediatypevideo];
 //2.用capturedevice创建输入流
 avcapturedeviceinput *input = [avcapturedeviceinput deviceinputwithdevice:capturedevice error:&error];
 if (!input) {
  nslog(@"%@", [error localizeddescription]);
  return no;
 }
 //3.创建媒体数据输出流
 avcapturemetadataoutput *capturemetadataoutput = [[avcapturemetadataoutput alloc] init];
 //4.实例化捕捉会话
 _capturesession = [[avcapturesession alloc] init];
 //4.1.将输入流添加到会话
 [_capturesession addinput:input];
 //4.2.将媒体输出流添加到会话中
 [_capturesession addoutput:capturemetadataoutput];
 //5.创建串行队列,并加媒体输出流添加到队列当中
 dispatch_queue_t dispatchqueue;
 dispatchqueue = dispatch_queue_create("myqueue", null);
 //5.1.设置代理
 [capturemetadataoutput setmetadataobjectsdelegate:self queue:dispatchqueue];
 //5.2.设置输出媒体数据类型为qrcode
 [capturemetadataoutput setmetadataobjecttypes:[nsarray arraywithobject:avmetadataobjecttypeqrcode]];
 //6.实例化预览图层
 _videopreviewlayer = [[avcapturevideopreviewlayer alloc] initwithsession:_capturesession];
 //7.设置预览图层填充方式
 [_videopreviewlayer setvideogravity:avlayervideogravityresizeaspectfill];
 //8.设置图层的frame
 [_videopreviewlayer setframe:_viewpreview.layer.bounds];
 //9.将图层添加到预览view的图层上
 [_viewpreview.layer addsublayer:_videopreviewlayer];
 //10.设置扫描范围
 capturemetadataoutput.rectofinterest = cgrectmake(0.2f, 0.2f, 0.8f, 0.8f);
 //10.1.扫描框
 _boxview = [[uiview alloc] initwithframe:cgrectmake(_viewpreview.bounds.size.width * 0.2f, _viewpreview.bounds.size.height * 0.2f, _viewpreview.bounds.size.width - _viewpreview.bounds.size.width * 0.4f, _viewpreview.bounds.size.height - _viewpreview.bounds.size.height * 0.4f)];
 _boxview.layer.bordercolor = [uicolor greencolor].cgcolor;
 _boxview.layer.borderwidth = 1.0f;
 [_viewpreview addsubview:_boxview];
 //10.2.扫描线
 _scanlayer = [[calayer alloc] init];
 _scanlayer.frame = cgrectmake(0, 0, _boxview.bounds.size.width, 1);
 _scanlayer.backgroundcolor = [uicolor browncolor].cgcolor;
 [_boxview.layer addsublayer:_scanlayer];
 nstimer *timer = [nstimer scheduledtimerwithtimeinterval:0.2f target:self selector:@selector(movescanlayer:) userinfo:nil repeats:yes];
 [timer fire];

 //10.开始扫描
 [_capturesession startrunning];
 return yes;
}

实现avcapturemetadataoutputobjectsdelegate协议方法

#pragma mark - avcapturemetadataoutputobjectsdelegate
- (void)captureoutput:(avcaptureoutput *)captureoutput didoutputmetadataobjects:(nsarray *)metadataobjects fromconnection:(avcaptureconnection *)connection
{
 //判断是否有数据
 if (metadataobjects != nil && [metadataobjects count] > 0) {
  avmetadatamachinereadablecodeobject *metadataobj = [metadataobjects objectatindex:0];
  //判断回传的数据类型
  if ([[metadataobj type] isequaltostring:avmetadataobjecttypeqrcode]) {
   [_lblstatus performselectoronmainthread:@selector(settext:) withobject:[metadataobj stringvalue] waituntildone:no];
   [self performselectoronmainthread:@selector(stopreading) withobject:nil waituntildone:no];
   _isreading = no;
  }
 }
}

实现计时器方法movescanlayer:(nstimer *)timer

- (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;
  [uiview animatewithduration:0.1 animations:^{
   _scanlayer.frame = frame;
  }];
 }
}

实现开始和停止方法

- (ibaction)startstopreading:(id)sender {
  if (!_isreading) {
   if ([self startreading]) {
    [_startbtn settitle:@"stop" forstate:uicontrolstatenormal];
    [_lblstatus settext:@"scanning for qr code"];
   }
  }
  else{
   [self stopreading];
   [_startbtn settitle:@"start!" forstate:uicontrolstatenormal];
  }
  _isreading = !_isreading;
}
-(void)stopreading{
 [_capturesession stoprunning];
 _capturesession = nil;
 [_scanlayer removefromsuperlayer];
 [_videopreviewlayer removefromsuperlayer];
}

以上内容就是本文给大家介绍ios原生二维码扫描的全部内容,希望大家喜欢。