最近项目遇到的需求:特定区域扫瞄并识别二维码,支持手电筒功能。好记性不如烂笔头,写下来方便后面自己用到。
1.动画部分,这部分可根据自己需要添加(不做过多描述)。
2.开启摄像头。iOS 10相机权限访问添在info.plist加Privacy - Camera Usage Description即可。
#define Height [UIScreen mainScreen].bounds.size.height //屏幕高
#define Width [UIScreen mainScreen].bounds.size.width //屏幕宽
#import <AVFoundation/AVFoundation.h>
@property(nonatomic,strong)AVCaptureSession *session;//输入输出的中间桥梁
@property (nonatomic,strong)AVCaptureVideoPreviewLayer *previewLayer;//相机实时预览图层
@property (nonatomic,strong)AVCaptureDevice *device;//用于获取相机的一些属性
@property (nonatomic,strong)CALayer * maskLayer;//扫描器灰色蒙板。
3.实现扫描功能
#pragma mark - 开始扫描二维码
- (void)startScanWithSize:(CGRect)frame
{
//获取摄像设备
if (self.device ==nil) {
self.device = [AVCaptureDevicedefaultDeviceWithMediaType:AVMediaTypeVideo];
}
//创建输入流
AVCaptureDeviceInput *input = [AVCaptureDeviceInputdeviceInputWithDevice:self.deviceerror:nil];
//判断输入流是否可用
if (input) {
//创建输出流
AVCaptureMetadataOutput * output = [[AVCaptureMetadataOutputalloc]init];
//***设置代理,在主线程里刷新,注意此时self需要设置AVCaptureMetadataOutputObjectsDelegate协议***
[output setMetadataObjectsDelegate:selfqueue:dispatch_get_main_queue()];
//初始化连接对象
if (self.session ==nil) {
self.session = [[AVCaptureSessionalloc]init];
}
//高质量采集率
[_sessionsetSessionPreset:AVCaptureSessionPresetHigh];
[_sessionaddInput:input];
[_sessionaddOutput:output];
//设置扫码支持的编码格式(如下设置条形码和二维码兼容)
output.metadataObjectTypes =@[AVMetadataObjectTypeQRCode,AVMetadataObjectTypeEAN13Code,AVMetadataObjectTypeEAN8Code,AVMetadataObjectTypeCode128Code];
//扫描区域大小的设置:(这部分也可以自定义,显示自己想要的布局)
self.previewLayer = [AVCaptureVideoPreviewLayerlayerWithSession:_session];
self.previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
self.previewLayer.frame = frame;//传入的相机预览图层大小(一般全屏)视情况而定
[self.view.layerinsertSublayer:self.previewLayeratIndex:0];
// 蒙版
self.maskLayer = [[CALayeralloc]init];
self.maskLayer.frame = CGRectMake(0,0, SCREEN_WIDTH,SCREEN_HEIGHT-64);
self.maskLayer.delegate =self;
[self.view.layerinsertSublayer:self.maskLayerabove:self.previewLayer];
[self.maskLayersetNeedsDisplay];
// 1.获取屏幕的frame
CGRect viewRect =CGRectMake(0,0, SCREEN_WIDTH,SCREEN_HEIGHT);
// 2.获取扫描容器的frame
CGRect containerRect =imageView.frame;//扫描框的大小
CGFloat x = containerRect.origin.y / viewRect.size.height;
CGFloat y = containerRect.origin.x / viewRect.size.width;
CGFloat width = containerRect.size.height / viewRect.size.height;
CGFloat height = containerRect.size.width / viewRect.size.width;
//扫描区域
output.rectOfInterest =CGRectMake(x, y, width, height);//坐标取值范围(0~1)整个屏幕(0,0,1,1);
}
}
然后://开始捕获图像:这步才开始
[_sessionstartRunning];
#pragma mark - 扫面结果在这个代理方法里获取到
-(void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection{
AVMetadataMachineReadableCodeObject *metaDataObject = [metadataObjectsobjectAtIndex:0];
NSString *valueStr = metaDataObject.stringValue;
//获取到信息后停止扫描:
[_sessionstopRunning];
//输出扫描字符串:
//NSLog(@"输出扫描字符串--%@ %@", valueStr);
}
//Note: 蒙板生成。需设置代理,并在退出页面时取消代理。
-(void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx{
if (layer ==self.maskLayer) {
UIGraphicsBeginImageContextWithOptions(self.maskLayer.frame.size,NO, 1.0);
CGContextSetFillColorWithColor(ctx, [UIColorcolorWithRed:0green:0blue:0alpha:0.6].CGColor);
CGContextFillRect(ctx,self.maskLayer.frame);
CGRect scanFrame = [self.viewconvertRect:imageView.framefromView:imageView.superview];//裁剪 imageView 扫描框
CGContextClearRect(ctx, scanFrame);
}
}
--分---------------割--------------------线--4.手电筒按钮事件
- (void)openLight:(UIButton *)sender{
sender.selected = !sender.selected;
AVCaptureDevice *device =self.device;
//修改前必须先锁定
[self.devicelockForConfiguration:nil];
//必须判定是否有闪光灯,否则如果没有闪光灯会崩溃
if ([self.devicehasFlash]) {
if (self.device.flashMode == AVCaptureFlashModeOff) {
self.device.flashMode = AVCaptureFlashModeOn;
self.device.torchMode = AVCaptureTorchModeOn;
} elseif (self.device.flashMode ==AVCaptureFlashModeOn) {
self.device.flashMode = AVCaptureFlashModeOff;
self.device.torchMode = AVCaptureTorchModeOff;
}
}
[device unlockForConfiguration];
}
5.结尾下图是成果(略丑...)