zoukankan      html  css  js  c++  java
  • 二维码扫描

    二维码扫描的实现

    #import "QRCodeViewController.h"
    #import <AVFoundation/AVFoundation.h>
    #import "Common.h"
    
    @interface QRCodeViewController ()<AVCaptureMetadataOutputObjectsDelegate>
    
    @property (nonatomic, strong)AVCaptureDevice *device;//设备
    @property (nonatomic, strong)AVCaptureInput *input;//输入端
    @property (nonatomic, strong)AVCaptureMetadataOutput *output;//输出端
    @property (nonatomic, strong)AVCaptureSession *session;//会话
    @property (weak, nonatomic) IBOutlet UIView *preView;//显示预览layer
    @property (nonatomic, weak)UIImageView *animationView;
    
    @property (nonatomic, strong)NSTimer *animationTimer;
    
    @end
    
    @implementation QRCodeViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view.
        
        //配置UI效果
        
        //添加扫描的边框
        UIImage *image = [UIImage imageNamed:@"qrcode_border"];
        UIImage *boundImage = [image resizableImageWithCapInsets:UIEdgeInsetsMake(25, 25, 26, 26)];
        UIImageView *imageView = [[UIImageView alloc] initWithImage:boundImage];
        //左边从70px开始
        
        CGFloat width = kScreenWidth - 70 *2;
        [imageView setFrame:CGRectMake(70, 170, width, width)];
        [self.view addSubview:imageView];
        
        
    //    添加上动画的图片
        UIImageView *animationView = [[UIImageView alloc] initWithFrame:CGRectMake(0, -width, width, width)];
        [animationView setImage:[UIImage imageNamed:@"qrcode_scanline_qrcode"]];
        //添加到方块视图上
        [imageView addSubview:animationView];
        //超出父视图区域不显示
        imageView.clipsToBounds = YES;
        self.animationView = animationView;
        
        self.animationTimer = [NSTimer scheduledTimerWithTimeInterval:.02f target:self selector:@selector(changeImage:) userInfo:nil repeats:YES];
        
        UIBarButtonItem *leftButton = [[UIBarButtonItem alloc] initWithTitle:@"取消" style:UIBarButtonItemStylePlain target:self action:@selector(cancel)];
        self.navigationItem.leftBarButtonItem = leftButton;
        
    }
    
    -(void)cancel{
        [self stopRead];
        [self.navigationController popViewControllerAnimated:YES];
    }
    
    -(void)viewDidAppear:(BOOL)animated{
        [super viewDidAppear:animated];
        //开始二维码扫描
        [self reading];
    }
    
    -(void)viewWillDisappear:(BOOL)animated{
        [super viewWillDisappear:animated];
        //停止二维码扫描
        [self stopRead];
    }
    
    
    -(void)changeImage:(NSTimer *)timer{
    
        //更新图片产生动画
        self.animationView.frame = CGRectOffset(self.animationView.frame, 0, 2);
        
        if (self.animationView.frame.origin.y >= self.animationView.superview.frame.size.height) {
            self.animationView.frame = CGRectMake(0, -CGRectGetHeight(self.animationView.superview.frame), self.animationView.frame.size.width, self.animationView.frame.size.height);
        }
    }
    
    //二维码扫描
    -(void)reading{
        //1.构造device  获得扫描设备:(摄像头)
        self.device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
        
        //2.构造input   生成连接设备和session的input
        NSError *error;
        self.input = [AVCaptureDeviceInput deviceInputWithDevice:self.device error:&error];
        
        //3.构造output,元数据
        self.output = [[AVCaptureMetadataOutput alloc] init];
        //4.session
        self.session = [[AVCaptureSession alloc] init];
        [self.session addInput:self.input];
        [self.session addOutput:self.output];
     
    //5.配置output
        //设置delegate,输出的类型    一定要将output添加到session中后,再设置
        dispatch_queue_t queue = dispatch_queue_create("queue", NULL);
        [self.output setMetadataObjectsDelegate:self queue:queue];
        [self.output setMetadataObjectTypes:self.output.availableMetadataObjectTypes];
        
        //6.添加预览功能  可以预览device捕捉到的画面
        AVCaptureVideoPreviewLayer *layer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:self.session];
        [layer setVideoGravity:AVLayerVideoGravityResizeAspectFill];
        [layer setFrame:self.view.bounds];
        [self.preView.layer addSublayer:layer];
        
        
        //生成一个图片,周围半透明,中间不透明,作为layer的mask层
        UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, NO, [[UIScreen mainScreen] scale]);
        CGContextRef context = UIGraphicsGetCurrentContext();
        //绘制底层的半透明效果
        CGContextSetRGBFillColor(context, 0, 0, 0, 0.9f);
        CGContextAddRect(context, self.view.bounds);
        CGContextFillPath(context);
        
        //绘制中间的不透明区域
        CGContextSetRGBFillColor(context, 1, 1, 1, 1.f);
        //中间方块区域
        CGContextAddRect(context, self.animationView.superview.frame);
        CGContextFillPath(context);
        
        //生成图片
        UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
        //释放资源
        UIGraphicsEndImageContext();
        
        CALayer *maskLayer= [[CALayer alloc] init];
        maskLayer.bounds = self.preView.bounds;
        maskLayer.position = self.preView.center;
        maskLayer.contents = (__bridge id)(image.CGImage);
        layer.mask = maskLayer;
        layer.masksToBounds = YES;
        
        //7.启动服务
        [self.session startRunning];
        [self.animationTimer fire];
    }
    //停止二维码扫描
    -(void)stopRead{
        [self.session stopRunning];
        //停止一个timer
        [self.animationTimer invalidate];
    }
    

    //代理服务,注意该方法的调用是在穿行队列中 -(void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection{ //接收元数据 if (metadataObjects.count != 0) { AVMetadataMachineReadableCodeObject *codeObj = metadataObjects[0]; if ([codeObj isKindOfClass:[AVMetadataMachineReadableCodeObject class]]) { NSLog(@"%@", [codeObj stringValue]); //在主线程中刷新UI [self performSelectorOnMainThread:@selector(cancel) withObject:nil waitUntilDone:YES]; } } }
  • 相关阅读:
    nginx default setting
    ubuntu dotnet core run 十月第一弹
    vwmare 十月第 1 弹
    学习 lind 语 里的一些组件使用。
    学习  解决用户验证、单点登录、api访问控制的开源框架 的 十月 第一弹:
    学习 lind api 十月 第5弹
    Data for the People: How to Make Our Post-Privacy Economy Work for You
    iframe高度的自适应
    dtree在ie6下点击页面报错
    前台页面分页对总页数的判断
  • 原文地址:https://www.cnblogs.com/10-19-92/p/4955776.html
Copyright © 2011-2022 走看看