美文网首页
iOS 使用原生API扫描二维码

iOS 使用原生API扫描二维码

作者: 黑暗森林的歌者 | 来源:发表于2016-08-09 17:37 被阅读87次

    添加需要的代理

    <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;
    

    相关文章

      网友评论

          本文标题:iOS 使用原生API扫描二维码

          本文链接:https://www.haomeiwen.com/subject/toddsttx.html