指示根视图:
self.window.rootviewcontroller = [[uinavigationcontroller alloc]initwithrootviewcontroller:[secondviewcontroller new]];
生成二维码:
// created by 韩俊强 on 15/11/27.
// copyright (c) 2015年 韩俊强. all rights reserved.
//
#import "secondviewcontroller.h"
@interface secondviewcontroller ()
@property (nonatomic, strong) uitextfield *tfcode;
@property (nonatomic, strong) uibutton *btngenerate;
@property (nonatomic, strong) uiimageview *imageview;
@end
@implementation secondviewcontroller
- (void)viewdidload {
[super viewdidload];
cgsize windowsize = [uiscreen mainscreen].bounds.size;
self.tfcode = [[uitextfield alloc] initwithframe:cgrectmake(10, 64, windowsize.width-100, 40)];
[self.view addsubview:self.tfcode];
self.tfcode.borderstyle = uitextborderstyleroundedrect;
self.btngenerate = [[uibutton alloc] initwithframe:cgrectmake(windowsize.width-100, 64, 90, 40)];
[self.view addsubview:self.btngenerate];
[self.btngenerate addtarget:self action:@selector(actiongenerate) forcontrolevents:uicontroleventtouchupinside];
self.btngenerate.backgroundcolor = [uicolor lightgraycolor];
[self.btngenerate settitle:@"生成" forstate:uicontrolstatenormal];
[self.btngenerate settitlecolor:[uicolor blackcolor] forstate:uicontrolstatenormal];
self.imageview = [[uiimageview alloc] initwithframe:cgrectmake(0, 0, 300, 300)];
[self.view addsubview:self.imageview];
self.imageview.center = cgpointmake(windowsize.width/2, windowsize.height/2);
self.tfcode.text = @"http://www.baidu.com";
}
- (void)actiongenerate
{
nsstring *text = self.tfcode.text;
nsdata *stringdata = [text datausingencoding: nsutf8stringencoding];
//生成
cifilter *qrfilter = [cifilter filterwithname:@"ciqrcodegenerator"];
[qrfilter setvalue:stringdata forkey:@"inputmessage"];
[qrfilter setvalue:@"m" forkey:@"inputcorrectionlevel"];
uicolor *oncolor = [uicolor blackcolor];
uicolor *offcolor = [uicolor whitecolor];
//上色
cifilter *colorfilter = [cifilter filterwithname:@"cifalsecolor" keysandvalues:@"inputimage",qrfilter.outputimage,@"inputcolor0",[cicolor colorwithcgcolor:oncolor.cgcolor],@"inputcolor1",[cicolor colorwithcgcolor:offcolor.cgcolor],nil];
ciimage *qrimage = colorfilter.outputimage;
//绘制
cgsize size = cgsizemake(300, 300);
cgimageref cgimage = [[cicontext contextwithoptions:nil] createcgimage:qrimage fromrect:qrimage.extent];
uigraphicsbeginimagecontext(size);
cgcontextref context = uigraphicsgetcurrentcontext();
cgcontextsetinterpolationquality(context, kcginterpolationnone);
cgcontextscalectm(context, 1.0, -1.0);
cgcontextdrawimage(context, cgcontextgetclipboundingbox(context), cgimage);
uiimage *codeimage = uigraphicsgetimagefromcurrentimagecontext();
uigraphicsendimagecontext();
cgimagerelease(cgimage);
self.imageview.image = codeimage;
扫描二维码:
#import "rootviewcontroller.h"
#import <avfoundation/avfoundation.h>
@interface rootviewcontroller ()<avcapturemetadataoutputobjectsdelegate,uialertviewdelegate>
@property (nonatomic, strong) uiview *scanrectview;
// 硬件设备
@property (strong, nonatomic) avcapturedevice *device;
//输入设备
@property (strong, nonatomic) avcapturedeviceinput *input;
//输出设备
@property (strong, nonatomic) avcapturemetadataoutput *output;
//桥梁.连接输入和输出设备,
@property (strong, nonatomic) avcapturesession *session;
@property (strong, nonatomic) avcapturevideopreviewlayer *preview;
@implementation rootviewcontroller
cgsize scansize = cgsizemake(windowsize.width*3/4, windowsize.width*3/4);
cgrect scanrect = cgrectmake((windowsize.width-scansize.width)/2, (windowsize.height-scansize.height)/2, scansize.width, scansize.height);
scanrect = cgrectmake(scanrect.origin.y/windowsize.height, scanrect.origin.x/windowsize.width, scanrect.size.height/windowsize.height,scanrect.size.width/windowsize.width);
self.device = [avcapturedevice defaultdevicewithmediatype:avmediatypevideo];
self.input = [avcapturedeviceinput deviceinputwithdevice:self.device error:nil];
self.output = [[avcapturemetadataoutput alloc]init];
[self.output setmetadataobjectsdelegate:self queue:dispatch_get_main_queue()];
self.session = [[avcapturesession alloc]init];
[self.session setsessionpreset:([uiscreen mainscreen].bounds.size.height<500)?avcapturesessionpreset640x480:avcapturesessionpresethigh];
[self.session addinput:self.input];
[self.session addoutput:self.output];
self.output.metadataobjecttypes=@[avmetadataobjecttypeqrcode];
self.output.rectofinterest = scanrect;
self.preview = [avcapturevideopreviewlayer layerwithsession:self.session];
self.preview.videogravity = avlayervideogravityresizeaspectfill;
self.preview.frame = [uiscreen mainscreen].bounds;
[self.view.layer insertsublayer:self.preview atindex:0];
self.scanrectview = [uiview new];
[self.view addsubview:self.scanrectview];
self.scanrectview.frame = cgrectmake(0, 0, scansize.width, scansize.height);
self.scanrectview.center = cgpointmake(cgrectgetmidx([uiscreen mainscreen].bounds), cgrectgetmidy([uiscreen mainscreen].bounds));
self.scanrectview.layer.bordercolor = [uicolor redcolor].cgcolor;
self.scanrectview.layer.borderwidth = 1;
//开始捕获
[self.session startrunning];
- (void)captureoutput:(avcaptureoutput *)captureoutput didoutputmetadataobjects:(nsarray *)metadataobjects fromconnection:(avcaptureconnection *)connection
if ( (metadataobjects.count==0) )
{
return;
}
if (metadataobjects.count>0) {
[self.session stoprunning];
avmetadatamachinereadablecodeobject *metadataobject = metadataobjects.firstobject;
//输出扫描字符串
uialertview *alert = [[uialertview alloc] initwithtitle:metadataobject.stringvalue message:@"" delegate:self cancelbuttontitle:@"ok" otherbuttontitles: nil nil];
[alert show];
- (void)alertview:(uialertview *)alertview willdismisswithbuttonindex:(nsinteger)buttonindex
新浪微博
最终效果:(由于扫描二维码无法展示效果,所以自己动手真机测试吧!)
ios7之前,开发者进行扫码编程时,一般会借助第三方库。常用的是zbarsdk,ios7之后,系统的avmetadataobject类中,为我们提供了解析二维码的接口。经过测试,使用原生api扫描和处理的效率非常高,远远高于第三方库。
官方提供的接口非常简单,代码如下:
<a target="_blank" href="http://my.oschina.net/u/2340880/blog/405847#">?</a>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<code>@interface viewcontroller ()<avcapturemetadataoutputobjectsdelegate></code><code>//用于处理采集信息的代理</code>
<code>{</code>
<code> </code><code>avcapturesession * session;</code><code>//输入输出的中间桥梁</code>
<code>}</code>
<code>@end</code>
<code>@implementation viewcontroller</code>
<code>- (</code><code>void</code><code>)viewdidload {</code>
<code> </code><code>[super viewdidload];</code>
<code> </code><code>// do any additional setup after loading the view, typically from a nib.</code>
<code> </code><code>//获取摄像设备</code>
<code> </code><code>avcapturedevice * device = [avcapturedevice defaultdevicewithmediatype:avmediatypevideo];</code>
<code> </code><code>//创建输入流</code>
<code> </code><code>avcapturedeviceinput * input = [avcapturedeviceinput deviceinputwithdevice:device error:nil];</code>
<code> </code><code>//创建输出流</code>
<code> </code><code>avcapturemetadataoutput * output = [[avcapturemetadataoutput alloc]init];</code>
<code> </code><code>//设置代理 在主线程里刷新</code>
<code> </code><code>[output setmetadataobjectsdelegate:self queue:dispatch_get_main_queue()];</code>
<code> </code>
<code> </code><code>//初始化链接对象</code>
<code> </code><code>session = [[avcapturesession alloc]init];</code>
<code> </code><code>//高质量采集率</code>
<code> </code><code>[session setsessionpreset:avcapturesessionpresethigh];</code>
<code> </code><code>[session addinput:input];</code>
<code> </code><code>[session addoutput:output];</code>
<code> </code><code>//设置扫码支持的编码格式(如下设置条形码和二维码兼容)</code>
<code> </code><code>output.metadataobjecttypes=@[avmetadataobjecttypeqrcode,avmetadataobjecttypeean13code, avmetadataobjecttypeean8code, avmetadataobjecttypecode128code];</code>
<code> </code>
<code> </code><code>avcapturevideopreviewlayer * layer = [avcapturevideopreviewlayer layerwithsession:session];</code>
<code> </code><code>layer.videogravity=avlayervideogravityresizeaspectfill;</code>
<code> </code><code>layer.frame=self.view.layer.bounds;</code>
<code> </code><code>[self.view.layer insertsublayer:layer atindex:0];</code>
<code> </code><code>//开始捕获</code>
<code> </code><code>[session startrunning];</code>
之后我们的ui上已经可以看到摄像头捕获的内容,只要实现代理中的方法,就可以完成二维码条形码的扫描:
<code>-(</code><code>void</code><code>)captureoutput:(avcaptureoutput *)captureoutput didoutputmetadataobjects:(nsarray *)metadataobjects fromconnection:(avcaptureconnection *)connection{</code>
<code> </code><code>if</code> <code>(metadataobjects.count>0) {</code>
<code> </code><code>//[session stoprunning];</code>
<code> </code><code>avmetadatamachinereadablecodeobject * metadataobject = [metadataobjects objectatindex : 0 ];</code>
<code> </code><code>//输出扫描字符串</code>
<code> </code><code>nslog(@</code><code>"%@"</code><code>,metadataobject.stringvalue);</code>
<code> </code><code>}</code>
通过上面的代码测试,我们可以发现系统的解析处理效率是相当的高,ios官方提供的api也确实非常强大,然而,我们可以做进一步的优化,将效率更加提高:
首先,avcapturemetadataoutput类中有一个这样的属性(在ios7.0之后可用):
@property(nonatomic) cgrect rectofinterest;
这个属性大致意思就是告诉系统它需要注意的区域,大部分app的扫码ui中都会有一个框,提醒你将条形码放入那个区域,这个属性的作用就在这里,它可以设置一个范围,只处理在这个范围内捕获到的图像的信息。如此一来,可想而知,我们代码的效率又会得到很大的提高,在使用这个属性的时候。需要几点注意:
1、这个cgrect参数和普通的rect范围不太一样,它的四个值的范围都是0-1,表示比例。
2、经过测试发现,这个参数里面的x对应的恰恰是距离左上角的垂直距离,y对应的是距离左上角的水平距离。
3、宽度和高度设置的情况也是类似。
3、举个例子如果我们想让扫描的处理区域是屏幕的下半部分,我们这样设置
<code>output.rectofinterest=cgrectmake(0.5,0,0.5, 1);</code>
具体apple为什么要设计成这样,或者是这个参数我的用法那里不对,还需要了解的朋友给个指导。