对于开发人员,即便资深老前辈也可能会出现没用过而短时间内解决不了的问题。今天我就遇到过求助了好几个大神都没能解决。而且在网上找了半天才找到。
先说下情况:公司三年老项目看着好坏参半的代码头疼的事就不说了。目前公司需求是二维码扫描效果不是很好,主要就是焦距问题。让我以微信作为参考。以前我也没去注意到,打开微信扫一扫的同时打开了我们项目的扫一扫对比了下结果
以下是设置相机单独抽出来的代码
- (void)setupCamera
{
captureDevice= [AVCaptureDevicedefaultDeviceWithMediaType:AVMediaTypeVideo];// Device
captureInput= [AVCaptureDeviceInputdeviceInputWithDevice:captureDeviceerror:nil];// Input
captureOutput= [[AVCaptureMetadataOutputalloc]init];// Output
[captureOutputsetMetadataObjectsDelegate:selfqueue:dispatch_get_main_queue()];
captureSession= [[AVCaptureSessionalloc]init];// Session
[captureSessionsetSessionPreset:AVCaptureSessionPresetHigh];
if([captureSessioncanAddInput:captureInput])
{
[captureSessionaddInput:captureInput];
}
if([captureSessioncanAddOutput:captureOutput])
{
[captureSessionaddOutput:captureOutput];
}
//条码类型AVMetadataObjectTypeQRCode
captureOutput.metadataObjectTypes=@[
AVMetadataObjectTypeQRCode,
AVMetadataObjectTypeUPCECode,
AVMetadataObjectTypeEAN8Code,
AVMetadataObjectTypeEAN13Code,
AVMetadataObjectTypeAztecCode,
AVMetadataObjectTypeCode39Code,
AVMetadataObjectTypeCode93Code,
AVMetadataObjectTypePDF417Code,
AVMetadataObjectTypeCode128Code,
AVMetadataObjectTypeCode39Mod43Code,
];
dispatch_async(dispatch_get_main_queue(), ^{
//更新界面
capturePreview=[AVCaptureVideoPreviewLayerlayerWithSession:captureSession];
capturePreview.videoGravity=AVLayerVideoGravityResizeAspectFill;
capturePreview.frame=self.view.bounds;
// Start
[captureSessionstartRunning];
});
}
此时只需要将试图layer层放大就可以完成效果:
[capturePreviewsetAffineTransform:CGAffineTransformMakeScale(1.5,1.5)];
需注意代码的顺序。给layer层设置frame的代码后放大。否则你会看到漆黑一片。
(后期插入补充):这段是测试人员发现的bug,由于上面将相机可视的layer层放大后导致超出控制器的view。此时在处理完扫描事件结果会退出当前扫描控制器。仔细看会发现控制器退出时卡在一半零点几秒后再完全退出。(与之前的版本进行对比)。此时修剪下capturePreview就行:
self.view.clipsToBounds=YES;
self.view.layer.masksToBounds=YES;
另一个问题:当你变形放大展示的layer层后二维码在可视界面之外也是可以进行扫描获取,于是乎我了解到将layer层的变大但是执行任务还是以整个layer大小来扫描执行。需要设置一个属性setRectOfInterest,他是摄像中AVCaptureMetadataOutput类的一个属性,他是通过一个CGRect来设置,但是有两点:1、它是横屏情况下的frame所以宽高和XY值需反向操作。就是按照竖屏模式应该将原先是XYWH要改为YXHW来设置。2、它是一个比例值以00开始为原点最大比例宽高为11(既全屏扫描情况下CGRect的写法为(0,0,1,1))。而且最大比例不是以手机尺寸比例,而是由capturePreview这个layer层为总比例。这也说明了为什么你能扫描超出屏幕尺寸外的二维码信息内容。
此处的scanCropRect接收了上面已设置好的中间扫描框的frame
CGFloat scanCropRectX = (capturePreview.frame.size.height - scanCropRect.size.height)/2;
CGFloat scanCropRectY = (capturePreview.frame.size.width - scanCropRect.size.width)/2;
//调整扫描位置
[captureOutputsetRectOfInterest:CGRectMake( scanCropRectX,scanCropRectY,scanCropRect.size.height/ capturePreview.frame.size.height ,scanCropRect.size.width/ capturePreview.frame.size.width )];
终于解决了扫描位置的问题