添加需要的代理
<AVCaptureMetadataOutputObjectsDelegate,UIAlertViewDelegate>
定义对象
//输入输出数据链
@property (nonatomic, strong) AVCaptureSession *session;
//是否读取数据
@property (nonatomic, assign) BOOL *readingCode;
初始化
//先判断是否获取相机权限
AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
if(authStatus == AVAuthorizationStatusRestricted || authStatus == AVAuthorizationStatusDenied){
UIAlertView *alert =[[UIAlertView alloc]initWithTitle:@"****" message:@"请在iPhone的“设置”-“隐私”-“相机”功能中,找到“****”打开相机访问权限" delegate:nil cancelButtonTitle:@"确定" otherButtonTitles: nil];
alert.delegate = self;
[alert show];
return;
}
//获取摄像头
AVCaptureDevice *captureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
//创建输入流
AVCaptureDeviceInput *captureInput = [AVCaptureDeviceInput deviceInputWithDevice:captureDevice error:nil];
//创建输出流
AVCaptureMetadataOutput *captureOutput = [[AVCaptureMetadataOutput alloc] init];
//把代理设置在主线程
[captureOutput setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
//初始化数据链
self.session = [[AVCaptureSession alloc] init];
[self.session setSessionPreset:AVCaptureSessionPresetHigh];//高质量采集数据
[self.session addInput:captureInput];
[self.session addOutput:captureOutput];
//扫描边框
UIView *borderView = [[UIView alloc] initWithFrame:CGRectMake((self.view.width - 250)/2, (self.view.height - 250 - self.myStartPosY)/2, 250, 250)];
borderView.backgroundColor = [UIColor clearColor];
borderView.layer.borderColor = [UIColor redColor].CGColor;
borderView.layer.borderWidth = 2.0;
[self.view addSubview:borderView];
//设置扫码支持的二维码格式(如需要其他格式,可是自己添加)
captureOutput.metadataObjectTypes=@[AVMetadataObjectTypeQRCode];
//显示摄像头画面
AVCaptureVideoPreviewLayer * captureLayer = [AVCaptureVideoPreviewLayer layerWithSession:self.session];
captureLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
captureLayer.frame = CGRectMake(0, self.myStartPosY, self.view.width, self.view.height - self.myStartPosY);
[self.view.layer insertSublayer:captureLayer atIndex:0];
//开始捕获
[self.session startRunning];
self.readingCode = YES;
优化建议:给captureOutput设置扫描区域,默认是全屏扫描。
AVCaptureMetadataOutput有个属性rectOfInterest就是设置识别区域的,不过这个rect 的四个参数是比例值,介于0-1之间。
AVCaptureVideoPreviewLayer有个方法:
(但是我运行的时候返回的rect的四个值都是 0,不知道为什么,所以没用这个方法,还是自己计算的范围)
//把一个在captureLayer坐标系中的rect 转换成 一个在metadataoutputs坐标系中的rect。
- (CGRect)metadataOutputRectOfInterestForRect:(CGRect)rectInLayerCoordinates;
//实现扫描区域是(20, 200, 300, 300)(计算范围)
CGRect outputInterest = CGRectMake(20/self.view.width, 200/self.view.height, 300/self.view.width, 300/self.view.height);
captureOutput.rectOfInterest = outputInterest;
实现代理回调
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection {
if (self.readingCode) {
if (metadataObjects && [metadataObjects count] > 0) {
AVMetadataMachineReadableCodeObject *metadataObject = [metadataObjects objectAtIndex:0];
//输出扫描字符串
NSLog(@"%@",metadataObject.stringValue);
if (metadataObject.stringValue.length > 0) {
self.readingCode = NO;
[self.session stopRunning];
self.session = nil;
}
}
}
}
扩展
使用layer的mask制作明暗对比界面
//阴影的view
UIView *maskView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.width, self.view.height)];
maskView.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.5];
[self.view addSubview:maskView];
//设置绘制的范围
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRect:maskView.bounds];
//绘制透明的范围
[maskPath appendPath:[[UIBezierPath bezierPathWithRoundedRect:CGRectMake(20, 200, 300, 300) cornerRadius:1] bezierPathByReversingPath]];
CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];
maskLayer.path = maskPath.CGPath;
maskView.layer.mask = maskLayer;
网友评论