首页 > 代码库 > 如何用IOS原生API扫描二维码
如何用IOS原生API扫描二维码
写这篇文章的主要原因不是展示如何使用 AVFoundation 来进行二维码扫描,更主要的是限制扫描二维码的范围。(因为默认的是全屏扫描) copyright www.stuhack.com
项目遇到扫描二维码的功能需求,这里我放弃了使用三方库,而采用了苹果原生的扫描。
原生的好处就是扫描特别快效率特别高,但是遇到一个问题就是不知道怎么去限制扫描范围。
还是先简单说一下怎么使用来进行二维码扫描吧。 内容来自学生黑客联盟
首先是要用到的几个类 学生黑客联盟 www.stuhack.com
@property (strong,nonatomic)AVCaptureDevice * device;
@property (strong,nonatomic)AVCaptureDeviceInput * input; www.stuhack.com
@property (strong,nonatomic)AVCaptureMetadataOutput * output;
@property (strong,nonatomic)AVCaptureSession * session; 内容来自学生黑客联盟
@property (strong,nonatomic)AVCaptureVideoPreviewLayer * preview;
他们之间的关系可以看下面的篇文章
传送门
下面分别创建他们
// Device
_device = [AVCaptureDevicedefaultDeviceWithMediaType:AVMediaTypeVideo];
// Input
_input = [AVCaptureDeviceInputdeviceInputWithDevice:self.deviceerror:nil];
// Output
_output = [[AVCaptureMetadataOutputalloc]init];
[_outputsetMetadataObjectsDelegate:selfqueue:dispatch_get_main_queue()];
// Session
_session = [[AVCaptureSessionalloc]init]; 内容来自学生黑客联盟
[_sessionsetSessionPreset:AVCaptureSessionPresetHigh];
if ([_sessioncanAddInput:self.input]) 内容来自学生黑客联盟
{
[_sessionaddInput:self.input];
}
if ([_sessioncanAddOutput:self.output])
{
[_sessionaddOutput:self.output];
}
// 条码类型 AVMetadataObjectTypeQRCode 内容来自学生黑客联盟
_output.metadataObjectTypes =@[AVMetadataObjectTypeQRCode];
// Preview
_preview =[AVCaptureVideoPreviewLayerlayerWithSession:_session]; 学盟网
_preview.videoGravity =AVLayerVideoGravityResizeAspectFill; www.stuhack.com
_preview.frame =self.view.layer.bounds;
[self.view.layerinsertSublayer:_previewatIndex:0];
本文来自学盟网(www.stuhack.com)
// Start
[_sessionstartRunning];
然后实现 AVCaptureMetadataOutputObjectsDelegate
#pragma mark AVCaptureMetadataOutputObjectsDelegate
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection
{
NSString *stringValue; 内容来自学生黑客联盟
if ([metadataObjectscount] >0)
{
//停止扫描
[_sessionstopRunning];
AVMetadataMachineReadableCodeObject * metadataObject = [metadataObjectsobjectAtIndex:0];
stringValue = http://www.mamicode.com/metadataObject.stringValue;
}
} 内容来自学生黑客联盟
到此为止就可以成功扫描二维码了,但是有个尴尬的问题,这时的扫描是全屏扫描的。即 www.stuhack.com
vc/CzuejrLDRy/nT0M/rtb21xLe9t6i2vMrUwcvSu7Hpo6y1q8rHtryyu9DQo6i2vMrHwOGjqaOs1+66872r0qq3xcb6tcTKsbryt6LP1sHL0ru49rHIvc+/ydLJtcS146GjPC9wPgo8cD48YnI+CjwvcD4KPHA+PC9wPgo8cD5AcHJvcGVydHkobm9uYXRvbWljKUNHUmVjdCByZWN0T2ZJbnRlcmVzdApOU19BVkFJTEFCTEVfSU9TKDdfMCk7PC9wPgrV4srHtcQgQVZDYXB0dXJlTWV0YWRhdGFPdXRwdXQg0ru49sr00NSjrMv8tcS94srNyscKCjxwPgpAZGlzY3Vzc2lvbjwvcD4KPHA+ClRoZSB2YWx1ZSBvZiB0aGlzIHByb3BlcnR5IGlzIGEgQ0dSZWN0IHRoYXQgZGV0ZXJtaW5lcyB0aGUgcmVjZWl2ZXI="s rectangle of interest for each frame of video.
The rectangle‘s origin is top left and is relative to the coordinate space of the device providing the metadata. Specifying
a rectOfInterest may improve detection performance for certain types of metadata. The default value of this property is the 学生黑客联盟 www.stuhack.com
value CGRectMake(0, 0, 1, 1). Metadata objects whose bounds do not intersect with the rectOfInterest will not be returned.
大概意思就是设置每一帧画面感兴趣的区域(字面意思),那岂不是就是设置扫描范围喽,大喜于是赶紧把rectOfInterest设置成中间框的frame,
[_outputsetRectOfInterest:CGRectMake((ScreenWidth-220)/2,60+64,220,220)];
//中间区域的宽和高都是220 ScreenWidth为设备屏幕宽度
但是却发现怎么扫描都不能成功了。于是又看了看上面的一段话。
第二句:区域的原点在左上方(后面才知道坑苦我了!),然后区域是相对于设备的大小的,默认值是CGRectMake(0, 0, 1, 1),这时候我才知道是有比例关系的,最大值才是1,也就是说只要除以相应的设备宽和高的大小不就行了?然后就改成
[_outputsetRectOfInterest:CGRectMake(((ScreenWidth-220)/2)/ScreenWidth,(60+64)/ScreenHigh,220/ScreenWidth,220/ScreenHigh)];
学生黑客联盟 www.stuhack.com
按说这样应该就完美了,但是才知道我还是高兴得太早了,一扫描才发现完全不是那么回事,差很多。
于是我就一点一点调,但是最后也没调成功,最后一狠心有设置了一个很确定的值。
[_output setRectOfInterest:CGRectMake(0.5,0.5,0.5, 0.5)];
本文来自学盟网(www.stuhack.com)
这次应该很确定是在右下方的四分之一区域吧,嘿嘿。
但是事实又一次打击了我,扫描后发现是左下的四分之一区域,也就是说rectOfInterest的原点是右上角!!!
回头又一想,即使右上角是原点那也应该没有影响啊,但是为什么不行呢,不会是原点的 X 和 Y 互换了吧?算了不管怎么着,试一试吧。
[_outputsetRectOfInterest:CGRectMake((60+64)/ScreenHigh,((ScreenWidth-220)/2)/ScreenWidth,220/ScreenWidth,220/ScreenHigh)];
又扫描了一下发现成功了!果然原点正确了,我只想说TMD!
但是宽和高又怎么对不上了?不会也互换了吧!赶紧试试
转载
[_outputsetRectOfInterest:CGRectMake((124)/ScreenHigh,((ScreenWidth-220)/2)/ScreenWidth,220/ScreenHigh,220/ScreenWidth)];
怀着忐忑的心情又试了试,完美扫描!OMG我想死的心都有了。于是用系统原生的扫描二维码就完美了!
如何用IOS原生API扫描二维码