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

    直接上项目代码 

    首先检查相机权限  
    
    AVAuthorizationStatus status = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
    if (status == AVAuthorizationStatusRestricted || status == AVAuthorizationStatusDenied) {
        // 没有授权访问相机权限 提示
        return;
    }
    
    
    #import "QrCodeVC.h"
    #import <AVFoundation/AVFoundation.h>
    #import <Masonry/Masonry.h>
    #import <pop/POP.h>
    #import "AppDelegate.h"
    #import "GoodsDetailVC.h"
    #import "WebViewVC.h"
    
    #define QRWH (ZKScreenW*283/375.0)
    #define TOP (ZKScreenH-QRWH)/2.0
    #define LEFT (ZKScreenW-QRWH)/2.0
    #define kScanRect CGRectMake(LEFT, TOP, QRWH, QRWH)
    #define kLineRect CGRectMake(LEFT+15, TOP, QRWH-30, 3)
    const static CGFloat animationTime = 2.0f;//扫描时长
    @interface QrCodeVC () <AVCaptureMetadataOutputObjectsDelegate>
    {
        CAShapeLayer *cropLayer;
    }
    @property (nonatomic, strong) AVCaptureDevice *device;
    @property (nonatomic, strong) AVCaptureDeviceInput *input;
    @property (nonatomic, strong) AVCaptureMetadataOutput *output;
    @property (nonatomic, strong) AVCaptureSession *session;
    @property (nonatomic, strong) AVCaptureVideoPreviewLayer *preview;
    /** 二维码View **/
    @property (nonatomic, strong) UIImageView *qrImageView;
    @property (nonatomic, strong) UIImageView *animationImageV;
    @property (nonatomic, assign) BOOL animationUp;
    @property (nonatomic, strong) UILabel *messageLb;
    @end
    @implementation QrCodeVC
    - (void)viewWillAppear:(BOOL)animated {
        [super viewWillAppear:animated];
        if (_session != nil) {
            [_session startRunning];
        }
        
        self.animationImageV.hidden = NO;
    }
    - (void)viewWillDisappear:(BOOL)animated {
        [super viewWillDisappear:animated];
    //    if (_session != nil) {
    //        [_session stopRunning];
    //    }
        self.animationImageV.hidden = YES;
    }
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        // 初始化扫描UI
        [self initView];
        
        // 初始化扫描二维码
        [self setupCamera];
    }
    - (void)initView {
        
        UIView *bgView = [[UIView alloc] initWithFrame:self.view.bounds];
        [self.view addSubview:bgView];
        bgView.backgroundColor = [UIColor clearColor];
        
        cropLayer = [[CAShapeLayer alloc] init];
        CGMutablePathRef path = CGPathCreateMutable();
        CGPathAddRect(path, nil, kScanRect);
        CGPathAddRect(path, nil, self.view.bounds);
        [cropLayer setFillRule:kCAFillRuleEvenOdd];
        [cropLayer setPath:path];
        [cropLayer setFillColor:[[UIColor blackColor] colorWithAlphaComponent:0.3].CGColor];
        [cropLayer setNeedsDisplay];
        [bgView.layer addSublayer:cropLayer];
        
        UIImageView *imageV = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"qrCode_bg"]];
        imageV.frame = kScanRect;
        [self.view addSubview:imageV];
        _qrImageView = imageV;
        
        UIImageView *animationImageV = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"qrCodeLine"]];
        animationImageV.frame = kLineRect;
        animationImageV.contentMode = UIViewContentModeScaleAspectFill;
        [self.view addSubview:animationImageV];
        _animationImageV = animationImageV;
        
        UILabel *messageLb = [[UILabel alloc] initWithFrame:CGRectMake(15, TOP-40, ZKScreenW-30, 20)];
        messageLb.text = getStringByKey(@"string_key_1592");
        messageLb.textAlignment = NSTextAlignmentCenter;
        messageLb.numberOfLines = 0;
        messageLb.font = [UIFont boldSystemFontOfSize:14];
        messageLb.textColor = [UIColor whiteColor];
        [self.view addSubview:messageLb];
        
        UILabel *titleLb = [[UILabel alloc] initWithFrame:CGRectMake(0, 30, ZKScreenW, 20)];
        titleLb.text = getStringByKey(@"string_key_1593");
        titleLb.textAlignment = NSTextAlignmentCenter;
        titleLb.font = [UIFont boldSystemFontOfSize:17];
        titleLb.textColor = [UIColor whiteColor];
        [self.view addSubview:titleLb];
        
        UIButton *backBtn = [[UIButton alloc] init];
        [backBtn setImage:[UIImage imageNamed:@"video_wirteBackArrow"] forState:UIControlStateNormal];
        [backBtn addTarget:self action:@selector(clickBackBtn) forControlEvents:UIControlEventTouchUpInside];
        [self.view addSubview:backBtn];
        [backBtn mas_makeConstraints:^(MASConstraintMaker *make) {
            make.top.equalTo(self.view.mas_top).with.offset(20);
            make.leading.equalTo(self.view.mas_leading);
            make.width.mas_equalTo(44);
            make.height.mas_equalTo(44);
        }];
    }
    - (void)clickBackBtn {
        [self.navigationController popViewControllerAnimated:YES];
    }
    - (CABasicAnimation *)qrAnimation {
        
        CGPoint starPoint = CGPointMake(_qrImageView.centerX  , _qrImageView.mj_y+3);
        CGPoint endPoint = CGPointMake(_qrImageView.centerX, _qrImageView.mj_y+QRWH-3);
        
        CABasicAnimation*translation = [CABasicAnimation animationWithKeyPath:@"position"];
        translation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
        
        translation.fromValue = [NSValue valueWithCGPoint:starPoint];
        translation.toValue = [NSValue valueWithCGPoint:endPoint];
        translation.duration = animationTime;
        translation.repeatCount = CGFLOAT_MAX;
        translation.autoreverses = YES;
        translation.removedOnCompletion = NO;
        
        return translation;
    }
    - (void)setupCamera {
        AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
        if (device==nil) {  // 设备没有摄像头
    //        UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"提示" message:@"设备没有摄像头" preferredStyle:UIAlertControllerStyleAlert];
    //        [alert addAction:[UIAlertAction actionWithTitle:@"确认" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
    //
    //        }]];
    //        [self presentViewController:alert animated:YES completion:nil];
            return;
        }
        _device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
        _input = [AVCaptureDeviceInput deviceInputWithDevice:self.device error:nil];
        _output = [[AVCaptureMetadataOutput alloc]init];
        [_output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
        
        //设置扫描区域
        CGFloat top = TOP/ZKScreenH;
        CGFloat left = LEFT/ZKScreenW;
        CGFloat width = QRWH/ZKScreenW;
        CGFloat height = QRWH/ZKScreenH;
        ///top 与 left 互换  width 与 height 互换
        [_output setRectOfInterest:CGRectMake(top,left, height, width)];
        
        
        // Session
        _session = [[AVCaptureSession alloc]init];
        [_session setSessionPreset:AVCaptureSessionPresetHigh];
        if ([_session canAddInput:self.input]) {
            [_session addInput:self.input];
        }
        
        if ([_session canAddOutput:self.output]) {
            [_session addOutput:self.output];
        }
        
        // 条码类型 AVMetadataObjectTypeQRCode
        [_output setMetadataObjectTypes:[NSArray arrayWithObjects:AVMetadataObjectTypeQRCode, nil]];
        
        // Preview
        _preview =[AVCaptureVideoPreviewLayer layerWithSession:_session];
        _preview.videoGravity = AVLayerVideoGravityResizeAspectFill;
        _preview.frame =self.view.layer.bounds;
        [self.view.layer insertSublayer:_preview atIndex:0];
        
        [_session startRunning];
        
        [_animationImageV.layer addAnimation:[self qrAnimation] forKey:nil];
    }
    #pragma mark AVCaptureMetadataOutputObjectsDelegate
    - (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection {
        NSString *stringValue;
        
        if ([metadataObjects count] >0) {
            //停止扫描
            [_session stopRunning];
            AVMetadataMachineReadableCodeObject *metadataObject = [metadataObjects objectAtIndex:0];
            stringValue = metadataObject.stringValue;
            if (stringValue.length > 0) {
                if ([stringValue containsString:@"sheinlink://applink/"]) {  // 调用deeplink跳转页面
                    AppDelegate *appDelegate=(AppDelegate*)[UIApplication sharedApplication].delegate;
                    [appDelegate openWithUrl:[NSURL URLWithString:stringValue]];
                } else if ([stringValue containsString:@"toApp"] && [stringValue containsString:@"goods_id="]) {  // 商品详情
                    NSRange sizeRange= [stringValue rangeOfString:@"goods_id="];
                    NSString *goodsId = [stringValue substringFromIndex:sizeRange.location+@"goods_id=".length];
                    if (goodsId) {
                        GoodsInfo *goodsInfo=[[GoodsInfo alloc] init];
                        goodsInfo.goods_id=[goodsId intValue];
                        UIStoryboard *sb=[UIStoryboard storyboardWithName:@"Goods" bundle:[NSBundle mainBundle]];
                        GoodsDetailVC *vc=[sb instantiateViewControllerWithIdentifier:@"GoodsDetailVC"];
                        vc.goodsInfo=goodsInfo;
                        [self.navigationController pushViewController:vc animated:YES];
                    }
                } else { // 跳转到普通网页
                    UIStoryboard *sb=[UIStoryboard storyboardWithName:@"Setting" bundle:[NSBundle mainBundle]];
                    WebViewVC *vc=[sb instantiateViewControllerWithIdentifier:@"WebViewVC"];
                    vc.titleText = @"";
                    vc.url = stringValue;
                    [self.navigationController pushViewController:vc animated:YES];
                }
            } else {
                // 没有获取到url
            }
        } else {
            NSLog(@"无扫描信息");
            return;
        }
    }
  • 相关阅读:
    day09 小练习 斐波那契数列 文件
    day09三目运算
    day08文件操作
    Nginx 内容缓存及常见参数配置
    阿里开源分布式事务解决方案 Fescar 全解析
    为什么你学不会递归?刷题几个月,告别递归,谈谈我的经验
    JavaScript 复杂判断的更优雅写法
    Java 线程本地 ThreadLocal 的分析和总结
    总结异步编程的六种方式
    JAVA8新特性(吐血整理)
  • 原文地址:https://www.cnblogs.com/10-19-92/p/9819968.html
Copyright © 2011-2022 走看看